:SAG - 用 SQL JOIN 代替 PageRank 做多跳 RAG 检索)
引言“图谱 RAG 的标准做法是离线构建全局图谱然后用 PageRank 做查询时的评分扩展——但 PageRank 有衰减链条越长分数越低。SAG 转而用 SQL JOIN 在查询时动态扩展没有衰减也不需要提前构建全局图谱。”这是每日一个开源项目系列的第152篇文章。今天的主角是SAGStructured Agentic Graph——Zleap-AI 开源的新一代多跳 RAG 框架有 arXiv 论文2606.15971背书。多跳检索的核心难题问题的答案需要把来自多个不同文档段落的信息串联起来。标准向量检索找到语义最相近的 chunk但语义最相近不等于能回答需要多步推理的问题。GraphRAG 和 HippoRAG 用知识图谱解决这个问题但有两个代价离线构建全局图谱成本高PageRank 评分在长链条下存在衰减。SAG 换了一条路不提前构建全局图谱在查询时用 SQL JOIN 做图结构扩展。每个 chunk 提取一个事件语义摘要和若干实体事件和实体之间的关联关系通过关系型数据库的外键表达多跳扩展就是 JOIN 操作确定性强没有衰减。你将学到什么SAG 的核心数据模型chunk → event entities 的设计逻辑查询时三步流程种子检索 → SQL 扩展 → 双路径最终选择为什么 SQL JOIN 比 PageRank 在长链多跳上表现更好与 HippoRAG 2、GraphRAG 的对比优势在哪里短板在哪里MCP 集成把 SAG 项目暴露为 Agent 可调用的工具全栈实现TypeScript PostgreSQL pgvector React前置知识了解 RAG 和多跳检索的基本概念了解知识图谱节点、边、多跳推理的基本概念了解 SQL JOIN 的概念项目背景项目简介SAGStructured Agentic Graph是一个文档检索系统用事件-实体图结构做知识组织通过 SQL JOIN 实现多跳检索专为 Agent 工作流设计。Structured指的是把非结构化文档转化成事件实体的结构化表示Agentic指的是每个 SAG 项目都内置 MCP 服务器可以作为 Agent 的工具端点使用Graph指的是通过 SQL JOIN 实现的查询时图遍历。作者/团队介绍团队: Zleap-AI官网: zleap.comarXiv: 2606.15971License: MIT基准测试仓库: Zleap-AI/SAG-Benchmark项目数据⭐ GitHub Stars:1,900 Forks: 87 License: MIT核心设计chunk → event entitiesSAG 的基础数据模型只有三种元素一个文档 chunk ↓ 一个 Event语义事件 ↑↕↓ 多个 Entities实体Event事件对这个 chunk 的语义摘要。每个 chunk 对应恰好一个 eventevent 保留了完整的语义。Entity实体从 chunk 里提取的命名实体作为图遍历的锚点。11 种类型时间、地点、人物、组织、群体、话题、作品、产品、动作、度量指标、标签。实体本身不携带独立语义只是连接不同事件的索引和扩展点。隐式超边一个 event 加上它所有的 entities构成一条隐式超边。这与 HyperGraphRAG 的思路类似但 SAG 不显式构建超图而是通过关系型数据库的外键关联来实现等效效果。为什么不用三元组Triple而用 Event 三元组方式 chunk → (Alice, works_at, Google) (Alice, attended, Meeting_001) (Bob, attended, Meeting_001) 关系被分解重建完整上下文需要多跳 Event 方式 chunk → Event: Alice 和 Bob 在 Meeting_001 上讨论了产品路线图 Entity: Alice, Bob, Meeting_001 完整语义保留在 evententity 作为连接点论文的消融实验证实在 MuSiQue 上超边event方案 Recall5 80.0%三元组方案 77.1%。两阶段架构离线阶段文档摄取文档 (Markdown / TXT) ↓ 文本分块chunking ↓ LLM 提取并行可配置并发数 每个 chunk → 1 个 event N 个 entities ↓ 写入两个后端同步 PostgreSQL → 结构化存储事件表、实体表、关联表 pgvector → 向量索引事件向量、实体向量 全文搜索索引 → BM25 实体匹配关键特性只有追加写入没有全局图谱的重建。新文档的摄取不影响已有数据不需要重新跑 PageRank 或重建图结构。在线阶段三步检索Step 1种子检索双路径并行Path A实体引导的结构化召回 1. LLM 从查询里提取实体 → 种子实体集 U_q 2. 向量相似度搜索实体索引阈值 0.9→ 扩展实体集 Û_q 3. SQL JOIN找到所有包含这些实体的事件 ℰR_entity {e | ∃u ∈ Û_q : SQL-Join(e, u)} Path B直接事件召回 查询向量 → 事件向量相似度搜索阈值 0.4 合并ℰR ℰR_entity ∪ ℰR_directStep 2查询时扩展SQL 多跳这是 SAG 的核心机制从种子事件集 ℰR 出发 ↓ 反向 JOIN取出种子事件关联的所有实体实体前沿 ↓ 正向 JOIN找到所有包含这些实体的新事件跨文档扩展 ↓ 重复 H 跳默认 H1 结果ℰ_cand ℰR ∪ ℰE这就是多跳的实现方式。如果文档 A 提到了实体 X文档 B 也提到了实体 X那么从文档 A 的事件出发一次 JOIN 就能找到文档 B 里的相关事件——即使这两个文档在向量空间里相距很远。Step 3最终选择双路径融合候选集 ℰ_cand100 个候选事件 ↓ 结构路径LLM 对候选链条重排序 → 取 top 5 事件 → 映射到 chunks 语义路径查询向量直接检索 chunk → 取 top 5 ↓ 合并去重 → 最终 10 个 chunksSQL JOIN vs. PageRank为什么 SAG 在长链多跳上更好HippoRAG 2 的做法离线构建全局知识图谱查询时用 Personalized PageRankPPR从种子节点出发分数沿图边传播。问题出在 PPR 的阻尼因子damping factor每经过一跳分数乘以(1-d)d 通常是 0.85也就是保留 15% 的概率。经过 2 跳节点得分乘以 0.15²0.02253 跳后几乎清零。HippoRAG 2 长链多跳的问题 答案需要路径A → B → C → D → E4跳 经过 PPRE 的得分 ≈ seed分数 × 0.15⁴ ≈ 0.0005 × seed分数 远端节点分数太低竞争不过直接相关的近端节点SAG 的 SQL JOIN 不传播分数只传播可达性实体 X 关联的所有事件JOIN 结果里一视同仁不论它们在图谱上距离种子有多远。MuSiQue 是这个差异的集中体现MuSiQue 专门设计了需要 4 步推理链的多跳问题HippoRAG 2 在这个数据集上明显弱于 SAG65.1% vs 80.0%。SAG 的短板在 2WikiMultiHopSAG 有一个固定的实体前沿裁剪预算50 个低频的桥接实体在裁剪时可能被截掉导致它在 2WikiMultiHop 上略低于 HippoRAG 288.0% vs 90.4%。基准测试结果使用bge-large-en-v1.5嵌入模型qwen3.6-flash作为 LLMRecall5 对比数据集SAGHippoRAG 2差距MuSiQue80.0%65.1%14.9ppHotpotQA96.5%94.4%2.1pp2WikiMultiHop88.0%90.4%-2.4pp平均 Recall279.30%68.14%11.16pp换用更强的NV-Embed-v2嵌入MuSiQue Recall5 达到81.71%说明提升来自结构设计本身不只是嵌入质量。消融实验配置MuSiQue R5完整 SAG80.0%去掉多跳扩展H069.4%去掉结构路径56.2%用轻量重排序器替换 LLM 重排序62.2%结论多跳扩展贡献了约 10.6pp 的提升LLM 重排序不可跳过差距 17.8pp。快速开始gitclone https://github.com/Zleap-AI/SAG.gitcdSAG# 配置环境变量cp.env.example .env# 编辑 .env填入 LLM API Key、Embedding API Key# 启动 PostgreSQL带 pgvectordockercompose up-d# 安装和初始化npminstallnpmrun db:setup# 启动开发服务器npmrun dev# WebUI: http://localhost:5173# API: http://localhost:4173.env 关键配置# LLMOpenAI 兼容 API LLM_BASE_URLhttps://api.openai.com/v1 LLM_API_KEYyour_key LLM_MODELqwen3.6-flash # 或 gpt-4o-mini # Embedding EMBEDDING_BASE_URLhttps://api.openai.com/v1 EMBEDDING_API_KEYyour_key EMBEDDING_MODELtext-embedding-3-large # 可选Rerank 模型 RERANK_MODELqwen3-rerank # 搜索模式 DEFAULT_SEARCH_MODEfast # fast / standard INGEST_CONCURRENCY5 # 并行摄取并发数两种搜索模式Fast 模式不调用 LLM 解析查询查询 → BM25 全文实体匹配 → SQL 多跳扩展 → 重排序 优点延迟低无 LLM 查询解析成本 适合实体名明确的查询Standard 模式LLM 提取查询实体查询 → LLM 提取实体 → 向量SQL 多跳扩展 → LLM 重排序 优点对模糊和自然语言问题更鲁棒 适合需要复杂推理的查询MCP 集成每个 SAG 项目自动暴露一个 MCP 服务器端点可以直接给 Claude Code 等 Agent 用{mcpServers:{sag:{command:npm,args:[run,mcp],env:{SAG_MCP_SOURCE_ID:your_project_id}}}}可用 MCP 工具工具功能sag_search搜索项目知识库sag_ingest_document上传新文档sag_explain_search解释特定问题的检索路径sag_get_event获取特定事件的详细信息Web UI 功能知识图谱浏览器可视化事件-实体节点支持拖拽、缩放、展开搜索链路追踪实时显示每次检索的内部步骤和各阶段延迟原始模型日志查看完整的 LLM / Embedding / Rerank 请求和响应项目隔离每个项目有独立的文档库、对话历史、图谱和 MCP 配置项目地址与资源GitHub: Zleap-AI/SAGarXiv: 2606.15971基准测试: Zleap-AI/SAG-Benchmark官网: zleap.com总结SAG 的核心贡献在于找到了一种轻量的多跳检索实现不构建全局知识图谱不依赖 PageRank 评分用关系型数据库的 JOIN 操作在查询时动态扩展图结构。这个选择有两个连带优势文档更新是追加写入不需要重建SQL JOIN 的可达性不受跳数影响不存在衰减。事件作为语义单元而非三元组的设计也是值得关注的每个 chunk 的完整语义被保留在一个 event 节点里实体只作为连接点使用。这比三元组方案在 MuSiQue 上高出近 3 个百分点验证了这个设计决策。短板是透明的固定裁剪预算在 2WikiMultiHop 上略逊于 HippoRAG 2在需要探索低频桥接实体的场景会漏掉一些关键路径。知道短板在哪里才能判断它是否适合你的场景。探索 PrimeSkills —— 精选 AI Agent 与技能的市场每一个都经过真实企业工作流验证去掉浮夸留下真正有用的。欢迎访问我的个人主页发现更多有价值的见解和有趣的产品。