每日一个开源项目(第152篇):SAG - 用 SQL JOIN 代替 PageRank 做多跳 RAG 检索

引言

"图谱 RAG 的标准做法是离线构建全局图谱,然后用 PageRank 做查询时的评分扩展------但 PageRank 有衰减,链条越长分数越低。SAG 转而用 SQL JOIN 在查询时动态扩展,没有衰减,也不需要提前构建全局图谱。"

这是"每日一个开源项目"系列的第152篇文章 。今天的主角是 SAG(Structured 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 的概念

项目背景

项目简介

SAG(Structured Agentic Graph)是一个文档检索系统,用事件-实体图结构做知识组织,通过 SQL JOIN 实现多跳检索,专为 Agent 工作流设计。

"Structured"指的是把非结构化文档转化成事件+实体的结构化表示;"Agentic"指的是每个 SAG 项目都内置 MCP 服务器,可以作为 Agent 的工具端点使用;"Graph"指的是通过 SQL JOIN 实现的查询时图遍历。

作者/团队介绍

项目数据

  • ⭐ GitHub Stars: 1,900+
  • 🍴 Forks: 87+
  • 📄 License: MIT

核心设计:chunk → event + entities

SAG 的基础数据模型只有三种元素:

markdown 复制代码
一个文档 chunk
    ↓
 一个 Event(语义事件)
    ↑↕↓
 多个 Entities(实体)

Event(事件):对这个 chunk 的语义摘要。每个 chunk 对应恰好一个 event,event 保留了完整的语义。

Entity(实体) :从 chunk 里提取的命名实体,作为图遍历的锚点。11 种类型:时间、地点、人物、组织、群体、话题、作品、产品、动作、度量指标、标签。实体本身不携带独立语义,只是"连接不同事件的索引和扩展点"。

隐式超边:一个 event 加上它所有的 entities,构成一条隐式超边。这与 HyperGraphRAG 的思路类似,但 SAG 不显式构建超图,而是通过关系型数据库的外键关联来实现等效效果。

vbnet 复制代码
为什么不用三元组(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
  完整语义保留在 event,entity 作为连接点

论文的消融实验证实:在 MuSiQue 上,超边(event)方案 Recall@5 = 80.0%,三元组方案 = 77.1%。


两阶段架构

离线阶段(文档摄取)

csharp 复制代码
文档 (Markdown / TXT)
    ↓
文本分块(chunking)
    ↓
LLM 提取(并行,可配置并发数):
  每个 chunk → 1 个 event + N 个 entities
    ↓
写入两个后端(同步):
  PostgreSQL     → 结构化存储(事件表、实体表、关联表)
  pgvector       → 向量索引(事件向量、实体向量)
  全文搜索索引   → BM25 实体匹配

关键特性:只有追加写入,没有全局图谱的重建。新文档的摄取不影响已有数据,不需要重新跑 PageRank 或重建图结构。

在线阶段(三步检索)

Step 1:种子检索(双路径并行)

css 复制代码
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_direct

Step 2:查询时扩展(SQL 多跳)

这是 SAG 的核心机制:

ini 复制代码
从种子事件集 ℰR 出发:
    ↓
反向 JOIN:取出种子事件关联的所有实体(实体前沿)
    ↓
正向 JOIN:找到所有包含这些实体的新事件(跨文档扩展)
    ↓
重复 H 跳(默认 H=1)

结果:ℰ_cand = ℰR ∪ ℰE

这就是"多跳"的实现方式。如果文档 A 提到了实体 X,文档 B 也提到了实体 X,那么从文档 A 的事件出发,一次 JOIN 就能找到文档 B 里的相关事件------即使这两个文档在向量空间里相距很远。

Step 3:最终选择(双路径融合)

css 复制代码
候选集 ℰ_cand(100 个候选事件)
    ↓
结构路径:LLM 对候选链条重排序 → 取 top 5 事件 → 映射到 chunks
语义路径:查询向量直接检索 chunk → 取 top 5
    ↓
合并去重 → 最终 10 个 chunks

SQL JOIN vs. PageRank:为什么 SAG 在长链多跳上更好

HippoRAG 2 的做法:离线构建全局知识图谱,查询时用 Personalized PageRank(PPR)从种子节点出发,分数沿图边传播。

问题出在 PPR 的阻尼因子(damping factor):每经过一跳,分数乘以 (1-d)(d 通常是 0.85),也就是保留 15% 的概率。经过 2 跳,节点得分乘以 0.15²=0.0225;3 跳后几乎清零。

css 复制代码
HippoRAG 2 长链多跳的问题:
答案需要路径:A → B → C → D → E(4跳)
经过 PPR:E 的得分 ≈ seed分数 × 0.15⁴ ≈ 0.0005 × seed分数
远端节点分数太低,竞争不过直接相关的近端节点

SAG 的 SQL JOIN 不传播分数,只传播可达性:实体 X 关联的所有事件,JOIN 结果里一视同仁,不论它们在图谱上距离种子有多远。

MuSiQue 是这个差异的集中体现:MuSiQue 专门设计了需要 4 步推理链的多跳问题,HippoRAG 2 在这个数据集上明显弱于 SAG(65.1% vs 80.0%)。

SAG 的短板在 2WikiMultiHop:SAG 有一个固定的实体前沿裁剪预算(50 个),低频的桥接实体在裁剪时可能被截掉,导致它在 2WikiMultiHop 上略低于 HippoRAG 2(88.0% vs 90.4%)。


基准测试结果

使用 bge-large-en-v1.5 嵌入模型,qwen3.6-flash 作为 LLM:

Recall@5 对比

数据集 SAG HippoRAG 2 差距
MuSiQue 80.0% 65.1% +14.9pp
HotpotQA 96.5% 94.4% +2.1pp
2WikiMultiHop 88.0% 90.4% -2.4pp
平均 Recall@2 79.30% 68.14% +11.16pp

换用更强的 NV-Embed-v2 嵌入,MuSiQue Recall@5 达到 81.71%,说明提升来自结构设计本身,不只是嵌入质量。

消融实验

配置 MuSiQue R@5
完整 SAG 80.0%
去掉多跳扩展(H=0) 69.4%
去掉结构路径 56.2%
用轻量重排序器替换 LLM 重排序 62.2%

结论:多跳扩展贡献了约 10.6pp 的提升,LLM 重排序不可跳过(差距 17.8pp)。


快速开始

bash 复制代码
git clone https://github.com/Zleap-AI/SAG.git
cd SAG

# 配置环境变量
cp .env.example .env
# 编辑 .env:填入 LLM API Key、Embedding API Key

# 启动 PostgreSQL(带 pgvector)
docker compose up -d

# 安装和初始化
npm install
npm run db:setup

# 启动开发服务器
npm run dev
# WebUI: http://localhost:5173
# API:   http://localhost:4173

.env 关键配置

env 复制代码
# LLM(OpenAI 兼容 API)
LLM_BASE_URL=https://api.openai.com/v1
LLM_API_KEY=your_key
LLM_MODEL=qwen3.6-flash          # 或 gpt-4o-mini

# Embedding
EMBEDDING_BASE_URL=https://api.openai.com/v1
EMBEDDING_API_KEY=your_key
EMBEDDING_MODEL=text-embedding-3-large

# 可选:Rerank 模型
RERANK_MODEL=qwen3-rerank

# 搜索模式
DEFAULT_SEARCH_MODE=fast           # fast / standard
INGEST_CONCURRENCY=5               # 并行摄取并发数

两种搜索模式

Fast 模式(不调用 LLM 解析查询):

sql 复制代码
查询 → BM25 全文实体匹配 → SQL 多跳扩展 → 重排序
优点:延迟低,无 LLM 查询解析成本
适合:实体名明确的查询

Standard 模式(LLM 提取查询实体):

sql 复制代码
查询 → LLM 提取实体 → 向量+SQL 多跳扩展 → LLM 重排序
优点:对模糊和自然语言问题更鲁棒
适合:需要复杂推理的查询

MCP 集成

每个 SAG 项目自动暴露一个 MCP 服务器端点,可以直接给 Claude Code 等 Agent 用:

json 复制代码
{
  "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 配置

项目地址与资源


总结

SAG 的核心贡献在于找到了一种轻量的多跳检索实现:不构建全局知识图谱,不依赖 PageRank 评分,用关系型数据库的 JOIN 操作在查询时动态扩展图结构。这个选择有两个连带优势:文档更新是追加写入不需要重建,SQL JOIN 的可达性不受跳数影响不存在衰减。

"事件"作为语义单元(而非三元组)的设计也是值得关注的:每个 chunk 的完整语义被保留在一个 event 节点里,实体只作为连接点使用。这比三元组方案在 MuSiQue 上高出近 3 个百分点,验证了这个设计决策。

短板是透明的:固定裁剪预算在 2WikiMultiHop 上略逊于 HippoRAG 2,在需要探索低频桥接实体的场景会漏掉一些关键路径。知道短板在哪里,才能判断它是否适合你的场景。


探索 PrimeSkills ------ 精选 AI Agent 与技能的市场,每一个都经过真实企业工作流验证,去掉浮夸,留下真正有用的。

欢迎访问我的个人主页,发现更多有价值的见解和有趣的产品。

相关推荐
冬奇Lab1 小时前
Workflow 系列(09):主流框架对比——Prompt-based、LangGraph、Temporal、n8n 如何选
人工智能·工作流引擎
程序员老猫2 小时前
vide coding 个人产品,那就从博客开始吧
人工智能·程序员·全栈
geo搜搜果数据2 小时前
实测5大AI平台品牌排名:复现GEO监测流程
人工智能·langchain·搜搜果
minge00013 小时前
【世界杯中的AI】(2026-07-05)当足球遇见AI:7月5日世界杯的“人机共舞”与冷门之夜
人工智能·科技·世界杯
IT_陈寒4 小时前
闭包陷阱让我加了两天班,JavaScript你真行
前端·人工智能·后端
wumingxiaoyao4 小时前
从 0 开始学 AI:第 2 课,AI、机器学习、深度学习和大模型是什么关系?
人工智能·深度学习·机器学习·ai·大模型·llm
2601_962683894 小时前
治理遗留系统中的“生肉 SQL”:一次用多模型协作优化慢查询的实战复盘
数据库·人工智能·sql
踩着两条虫4 小时前
可视化 vs 终端 vs 云端:VTJ.PRO、Claude Code、Codex 三强横评
前端·vue.js·人工智能·低代码·架构