Agentic RAG 模式
调研日期:2025-06-22 · 未实测,以源码/docs/社区为准
一句话定位
从”固定管线检索”到”Agent 自主决定何时/查什么/怎么验证”——RAG 编排方式的演进光谱,以及各模式在 WeKnora / Dify / LangChain 中的落地形态。
RAG 管线段标注
本篇横跨 Retrieve → Generate 两段,核心关注编排层——谁来决定检索策略、何时二次检索、如何验证结果。
日常类比
想象你要回答一个复杂问题”公司去年各产品线的 ROI 排名”:
- Naive RAG:直接在文件柜里按关键词翻一遍,把找到的第一批文件丢给秘书写答案。万一关键词偏了,答案就歪了。
- Advanced RAG:秘书先帮你把问题说清楚(”你是要财务 ROI 还是用户 ROI?”),翻完文件后再挑最相关的几份(Rerank),才写答案。
- Modular RAG:文件柜、秘书、审核员都是独立岗位,可以按需替换——今天用语义检索员,明天换 BM25 检索员,流程不变。
- Graph RAG:不只翻文件,还翻”关系网”——通过”产品线 A 的负责人也是产品线 B 的顾问”这类关系,找到间接相关的文件。
- Agentic RAG:你不是自己翻文件,而是派一个”研究助理”——他会先判断需要查哪些数据源,查完第一轮发现缺数据,自主决定再查第二轮,最后验证数字自洽才交报告。
- Multi-hop RAG:研究助理不只查一轮——先查”去年有哪些产品线”,再查”每个产品线的营收”,再查”每个产品线的投入”,三跳之后才能算出 ROI 排名。
类比边界:Agentic RAG 的”自主决策”受限于 LLM 的推理能力和 token 预算,不是无限递归。Multi-hop 的”多跳”每次跳转都可能引入误差,跳数越多误差累积越大。
从类比到技术:编排层的核心问题
以上六种类比指向同一个技术问题:谁来编排检索?
在 Naive RAG 中,编排者是写代码的工程师——检索策略在部署时就固化了,运行时无法改变。在 Advanced 和 Modular RAG 中,编排者仍然是工程师,但通过配置而非代码来调整——灵活性高了一些,但本质还是”预设策略”。在 Agentic RAG 中,编排者换成了 LLM——每次查询时 LLM 实时决定检索策略,这才是”自主”的含义。在 Multi-hop RAG 中,LLM 不只决定策略,还决定推理链的长度和方向——每一步的输出成为下一步的输入,形成”思考链”。
所以六种模式的演进,本质上是编排权从工程师逐步让渡给 LLM 的过程。越往后,LLM 的决策权越大,灵活性越高,但可控性越低。选择哪种模式,核心是回答一个问题:你愿意给 LLM 多少决策权?
如果你的场景高度确定(企业知识库、固定查询模式),把决策权留在工程师手里(固定管线)效率更高。如果你的场景高度不确定(研究调查、开放域问答),把决策权交给 LLM(Agentic)效果更好。大多数生产场景落在中间——部分决策权给 LLM,部分保留在工程师手里,这就是”半 Agentic”模式。
六种模式总览
从最简单到最复杂,六种 RAG 模式形成一条明确的演进光谱。核心区分维度是谁在编排检索:固定代码 → 可配置管线 → LLM 自主决策。
| # | 模式 | 编排者 | 检索次数 | 典型延迟 | 工程复杂度 | 检索质量上限 |
|---|---|---|---|---|---|---|
| 1 | Naive RAG | 固定代码 | 1 | 低 | 低 | ★★ |
| 2 | Advanced RAG | 固定代码 + 优化模块 | 1-2 | 中 | 中 | ★★★ |
| 3 | Modular RAG | 可组合管线 | 1-N | 中 | 中 | ★★★ |
| 4 | Graph RAG | 固定代码 + 图谱引擎 | 1-2 | 中-高 | 高 | ★★★★ |
| 5 | Agentic RAG | LLM 自主 | 1-N | 高(不可预测) | 高 | ★★★★ |
| 6 | Multi-hop Agentic | LLM 自主 + 推理链 | N(逐跳递增) | 很高 | 很高 | ★★★★★ |
检索质量”上限”是理论值——实际能否达到取决于实现质量、数据质量和 LLM 能力。详见 RAG 评估方法论
模式 1:Naive RAG
一句话
Query → 单路检索 → 生成。无融合、无 Rerank、无纠偏。最原始的 RAG 形态。
日常类比
你在图书馆查资料:只看目录索引(一种检索方式),找到哪本算哪本,直接翻到相关页抄下来交差。如果关键词写错了,或者目录没收录这本书,你就永远找不到。
架构与数据流
flowchart LR
Q[用户查询] --> E[Embed<br>查询向量化]
E --> V[向量数据库<br>相似度检索 Top-K]
V --> C[拼接上下文<br>query + chunks]
C --> L[LLM 生成]
L --> A[答案]
style Q fill:#f9f9f9
style V fill:#e8f4e8
style L fill:#e8e8f4
数据流详解:
- 用户输入 query
- query 经 embedding 模型转为向量
- 在向量数据库中做余弦相似度检索,取 Top-K 个 chunk
- 把 query 和 K 个 chunk 拼成 prompt
- LLM 基于prompt 生成答案
伪代码
def naive_rag(query, vector_db, llm, top_k=5):
# 1. 查询向量化
q_vec = embed(query)
# 2. 单路检索
chunks = vector_db.similarity_search(q_vec, k=top_k)
# 3. 拼接生成
context = "\n".join([c.text for c in chunks])
answer = llm.generate(f"基于以下内容回答问题:\n{context}\n问题:{query}")
return answer
优势
- 实现最简单——5 行核心逻辑即可跑通
- 延迟最低——一次检索 + 一次生成
- 调试最容易——管线无分支,问题定位直接
劣势与踩坑
| 坑 | 为什么 | 后果 |
|---|---|---|
| 单信号召回率天花板 | 只靠向量相似度,精确关键词(错误码、API 名)召回差 | 查”errno ECONNREFUSED”可能搜不到 |
| 无 Rerank | Top-K 里可能混入低相关 chunk | 生成时被无关内容干扰,产生幻觉 |
| 无纠偏 | 检索结果差时无法自救 | “不知道就说不知道”做不到 |
| chunk 边界问题 | 固定长度分块可能切断语义 | 关键信息跨块,检索只拿到一半 |
代表实现
- AnythingLLM 默认模式(单路向量检索)
- 早期 LangChain
RetrievalQAchain - LlamaIndex 默认
query_engine
何时选用
- 文档量 < 1000 篇,查询模式单一
- 原型验证阶段,需要最快跑通
- 延迟要求极严(< 1s 端到端)
Naive RAG 的三个根本问题
Naive RAG 看起来”能用就行”,但它有三个根本性问题,后续所有模式都是在逐一解决:
问题一:信号单一。向量检索只捕获”语义相似”这一种信号。但用户的查询意图是多样的——有时需要精确匹配(查错误码),有时需要语义理解(查同义表达),有时需要结构推理(查关联关系)。一种信号不可能覆盖所有意图,这是召回率天花板的根本原因。
问题二:无质量把关。检索回来的 Top-K 个 chunk 直接拼进 prompt,不管里面有没有低相关甚至无关的内容。LLM 面对混杂的上下文,要么被无关信息干扰产生幻觉,要么被低质量内容带偏推理方向。这是生成质量不稳定的根本原因。
问题三:无自救能力。当检索结果很差时(关键词偏了、文档没覆盖、向量模型不理解),整个管线没有任何纠偏机制——不会重写查询,不会换检索方式,不会告诉你”我没找到相关信息”。这是鲁棒性差的根本原因。
后续模式的演进逻辑:
- Advanced RAG 解决问题二(Rerank 把关)和问题一的局部(Query Rewriting 扩大信号覆盖)
- Modular RAG 不解决新问题,但让解决方案可组合替换
- Graph RAG 解决问题一的根本(增加结构信号)
- Agentic RAG 解决问题三的根本(Agent 自纠偏)
- Multi-hop RAG 解决问题一的极端情况(多跳推理需要多轮信号累积)
Naive RAG 是所有后续模式的起点。理解它的三个根本问题,才知道后面每一步优化在解决什么问题。
模式 2:Advanced RAG
一句话
在 Naive RAG 的检索前后插入优化模块——检索前改查询(rewriting / HyDE),检索后精筛结果(Rerank / 过滤),一次检索但质量大幅提升。
日常类比
Naive RAG 是你直接去文件柜翻;Advanced RAG 是翻之前先想清楚”我到底要什么”(query rewriting),或者先写一份”假答案”去比对(HyDE),翻完后再让审核员挑出真正相关的(Rerank)。同样的文件柜,同样的翻一次,但前后各加一步,结果质量天差地别。
架构与数据流
flowchart TD
Q[用户查询] --> PR{检索前优化}
PR -->|Query Rewriting| QR[改写查询<br>同义词扩展/拆子问题]
PR -->|HyDE| HY[假设文档嵌入<br>LLM 生成假答案 → 向量化]
PR -->|无优化| Q0[原始查询]
QR --> V[向量检索 Top-K]
HY --> V
Q0 --> V
V --> PO{检索后优化}
PO -->|Rerank| RR[交叉编码器精排<br>取 Top-N of K]
PO -->|过滤| FT[相关性阈值过滤]
PO -->|无优化| C0[原始 Top-K]
RR --> C[拼接上下文]
FT --> C
C0 --> C
C --> L[LLM 生成]
L --> A[答案]
检索前优化详解
Query Rewriting(查询改写)
核心思想:用户的原始 query 往往不是最佳检索词。
| 改写策略 | 原理 | 示例 |
|---|---|---|
| 同义词扩展 | “离职”→”离职/辞职/解聘/退出” | 覆盖文档中的不同表述 |
| 子问题拆解 | “对比 A 和 B”→[“A 的特点”,”B 的特点”] | 分别检索再合并 |
| 回退提示(Step-back) | “Python 3.12 的 match 语法”→”Python 模式匹配发展历史” | 从具体退到抽象,提高召回 |
| 查询压缩 | 多轮对话中的指代消解:”它怎么用?”→”Python match 语句怎么用?” | 补平上下文 |
HyDE(Hypothetical Document Embedding)
核心思想:让 LLM 先生成一个”假设性答案”,用这个假答案的向量去检索——假答案的语义更接近真实文档,比直接用短 query 检索效果好。
类比:你问”怎么炒宫保鸡丁”,与其用这几个字去搜索,不如先让大厨写一份”可能的做法”,再用这份做法去和菜谱库比对——因为做法的文本和菜谱的文本语义更接近。
def hyde_retrieve(query, llm, vector_db, top_k=5):
# 1. LLM 生成假设性答案
hypothetical_doc = llm.generate(
f"请写一段回答以下问题的文档内容:\n{query}"
)
# 2. 用假设答案的向量检索(而非 query 本身)
h_vec = embed(hypothetical_doc)
chunks = vector_db.similarity_search(h_vec, k=top_k)
return chunks
HyDE 的 trade-off:
- 优势:对短 query / 抽象 query 效果显著(论文报告提升 10-20% 召回率)
- 劣势:额外一次 LLM 调用(成本 + 延迟);LLM 生成的假答案如果方向偏了,检索更差
Rerank(检索后精排)
核心思想:向量检索的粗排(bi-encoder)速度够快但精度不够——用交叉编码器(cross-encoder)对 query + 每个 chunk 做精细打分,只留最相关的。
def rerank(query, chunks, reranker, top_n=3):
# cross-encoder: 同时编码 query 和 chunk,输出相关性分数
scores = [reranker.score(query, chunk.text) for chunk in chunks]
ranked = sorted(zip(chunks, scores), key=lambda x: x[1], reverse=True)
return [chunk for chunk, score in ranked[:top_n]]
WeKnora 的复合 Rerank 三路加权(0.6 模型分 + 0.3 基础分 + 0.1 来源分)就是一个 Advanced RAG 的检索后优化实例。详见 精读: WeKnora
伪代码(完整 Advanced RAG)
def advanced_rag(query, llm, vector_db, reranker, top_k=10, top_n=3):
# --- 检索前优化 ---
# Query Rewriting: 拆子问题
sub_queries = llm.generate(f"将以下问题拆为子问题:{query}")
sub_queries = parse_sub_queries(sub_queries) # ["A的特点", "B的特点"]
# --- 多路检索 ---
all_chunks = []
for sq in sub_queries:
vec = embed(sq)
chunks = vector_db.similarity_search(vec, k=top_k)
all_chunks.extend(chunks)
# --- 检索后优化 ---
# Rerank: 交叉编码器精排
ranked_chunks = rerank(query, all_chunks, reranker, top_n=top_n)
# --- 生成 ---
context = "\n".join([c.text for c in ranked_chunks])
answer = llm.generate(f"基于以下内容回答:\n{context}\n问题:{query}")
return answer
优势
- 在不增加检索次数的前提下显著提升质量
- Rerank 几乎总是值得加(成本增加 ~50ms,质量提升 15-30%)
- HyDE 对短/抽象 query 效果显著
劣势与踩坑
| 坑 | 为什么 | 后果 |
|---|---|---|
| HyDE 方向偏了更差 | LLM 对领域不熟时生成的假答案带偏检索 | 医疗/法律等严谨领域慎用 |
| Rerank 模型泛化性 | 通用 reranker 对领域术语不敏感 | 领域特化需要微调 reranker |
| 子问题拆解不完整 | LLM 可能遗漏关键子问题 | 部分信息缺失 |
代表实现
- WeKnora 的 RRF 融合 + 复合 Rerank
- RAGFlow 的 DeepDoc 解析 + Rerank
- Dify 的查询改写配置
- LangChain 的 MultiQueryRetriever
何时选用
- 文档量中等(1K-100K 篇),查询模式多样
- 对质量有要求但延迟预算有限
- 90% 的生产 RAG 系统应该至少做到这一级
Advanced RAG 的设计哲学
Advanced RAG 背后有一个核心设计哲学:不改变管线的主干流程,只在关键节点插入优化。这和软件工程中的”装饰器模式”如出一辙——核心逻辑不变,在前后各加一层增强。
为什么这个哲学重要?因为它意味着升级成本极低。你的 Naive RAG 代码不需要重构,只需要在检索前加一个函数调用(查询改写),在检索后加一个函数调用(Rerank),质量就能提升三十个百分点以上。这在工程上的投入产出比是所有升级中最高的。
但 Advanced RAG 也有天花板:它仍然是固定管线——检索前优化 → 检索 → 检索后优化 → 生成,这个顺序不会变。当查询需要”查完 A 发现不够,再查 B”这种动态决策时,固定管线就无能为力了。这正是 Agentic RAG 要解决的问题。
Advanced RAG 在五个项目中的具体形态
| 项目 | 检索前优化 | 检索后优化 | 特殊之处 |
|---|---|---|---|
| WeKnora | 无内建查询改写 | 复合 Rerank(三路加权) | Rerank 同时考虑模型分、基础分、来源分,是最精细的实现 |
| Dify | 可配置查询改写 | 可选 Rerank 节点 | 在 Workflow 中拖拽配置,非代码 |
| RAGFlow | DeepDoc 解析优化 | Rerank | 检索前优化在文档摄入阶段而非查询阶段 |
| AnythingLLM | 无 | 无 | 纯 Naive,升级 Advanced 需要自行开发 |
| FastGPT | 可配置查询改写 | Rerank 节点 | 类似 Dify 的 Workflow 配置 |
Advanced RAG 是性价比最高的模式。从 Naive 升级到 Advanced 的投入产出比远高于后续任何升级。
模式 3:Modular RAG
一句话
把 RAG 管线拆成可插拔的独立模块——检索器、Reranker、生成器各自可替换,按需组合,像乐高积木一样搭建 RAG 流程。
日常类比
Naive RAG 是一体机电脑——想换显卡得整台换。Modular RAG 是自己组装的台式机——今天插这块显卡,明天换那块,主板和电源不用动。每个模块独立升级,整体架构不变。
架构与数据流
flowchart TD
Q[用户查询] --> I[Indexer 模块<br>可选: 分块/解析/向量化]
I --> R{Retriever 模块<br>可替换}
R -->|BM25| R1[关键词检索器]
R -->|Dense| R2[向量检索器]
R -->|Hybrid| R3[混合检索器]
R -->|Graph| R4[图谱检索器]
R1 --> F{Fusion 模块<br>可替换}
R2 --> F
R3 --> F
R4 --> F
F -->|RRF| F1[倒数排名融合]
F -->|Weighted| F2[加权融合]
F1 --> RK{Reranker 模块<br>可替换}
F2 --> RK
RK -->|Cross-Encoder| RK1[交叉编码器]
RK -->|ColBERT| RK2[晚期交互模型]
RK -->|LLM| RK3[LLM 判断相关性]
RK1 --> G{Generator 模块<br>可替换}
RK2 --> G
RK3 --> G
G -->|OpenAI| G1[GPT-4]
G -->|Local| G2[Llama3]
G --> A[答案]
核心设计原则
| 原则 | 含义 | 为什么重要 |
|---|---|---|
| 单一职责 | 每个模块只做一件事 | 替换/测试/优化互不干扰 |
| 接口标准化 | 模块间通过标准协议通信 | 新模块即插即用 |
| 配置驱动 | 模块选择通过配置而非代码 | 非开发者也能调管线 |
| 可观测性 | 每个模块输入/输出可追踪 | 定位质量问题到具体模块 |
WeKnora 的模块化实践
WeKnora 的 EventManager 事件总线本质上是一个 Modular RAG 编排器:
EventManager
├── Indexer: 文档摄入 → 分块 → 向量化 → 入库
├── Retriever: BM25 + Vector + Graph 三路
├── Fusion: RRF (k=60) 融合三路排名
├── Reranker: 复合 Rerank (0.6/0.3/0.1)
└── Generator: LLM 生成 + 引用溯源
每个环节都是独立 Go package,可以单独替换。例如把 Reranker 从 cross-encoder 换成 LLM-based,只需实现 Reranker 接口。详见 精读: WeKnora
伪代码
class ModularRAG:
def __init__(self, indexer, retriever, fusion, reranker, generator):
self.indexer = indexer # 可替换
self.retriever = retriever # 可替换
self.fusion = fusion # 可替换
self.reranker = reranker # 可替换
self.generator = generator # 可替换
def run(self, query):
# 管线编排,每步可替换实现
indexed_q = self.indexer.process(query)
multi_results = self.retriever.retrieve(indexed_q)
fused = self.fusion.merge(multi_results)
reranked = self.reranker.rerank(indexed_q, fused)
answer = self.generator.generate(indexed_q, reranked)
return answer
# 配置驱动:不同场景用不同模块组合
production_rag = ModularRAG(
indexer=ChineseTokenizer(), # 中文分词
retriever=WeKnoraTripleRetriever(), # 三路检索
fusion=RRFFusion(k=60), # RRF 融合
reranker=CompositeReranker(), # 复合 Rerank
generator=GPT4Generator() # GPT-4 生成
)
lightweight_rag = ModularRAG(
indexer=SimpleTokenizer(),
retriever=DenseRetriever(), # 只走向量
fusion=NoFusion(), # 无需融合
reranker=CrossEncoderReranker(), # 单路 Rerank
generator=Llama3Generator() # 本地模型
)
优势
- 模块独立升级——换 Reranker 不影响 Retriever
- 配置驱动——同一套代码支持多场景
- 问题定位精准——哪个模块的指标下降一目了然
- 团队协作友好——不同团队负责不同模块
劣势与踩坑
| 坑 | 为什么 | 后果 |
|---|---|---|
| 模块间隐式依赖 | Reranker 期望 Retriever 输出特定格式 | 换模块后接口不匹配 |
| 全局调优困难 | 每个模块局部最优 ≠ 全局最优 | 各自调好的参数组合起来反而差 |
| 配置爆炸 | N 个模块各有 M 种选择 | 测试组合数指数增长 |
代表实现
- WeKnora EventManager 架构
- Dify Workflow 可视化编排
- FastGPT 工作流节点
- LangChain LCEL (LangChain Expression Language)
何时选用
- 多场景复用同一套 RAG 基础设施
- 团队多人协作,各负责不同模块
- 需要频繁 A/B 测试不同模块组合
Modular RAG 与微服务架构的对照
Modular RAG 的设计思想和微服务架构高度相似——把单体应用拆成独立服务,每个服务可独立部署、独立升级、独立扩缩容。对照关系:
| 微服务概念 | Modular RAG 对应 | 含义 |
|---|---|---|
| 服务 | 模块(Retriever/Reranker/Generator) | 独立部署和升级 |
| API 网关 | 管线编排器 | 决定请求经过哪些服务 |
| 服务发现 | 模块注册表 | 动态发现可用模块 |
| 链路追踪 | 模块输入/输出日志 | 追踪请求经过的每一跳 |
| 熔断器 | 质量检查点 | 某模块输出质量差时跳过或降级 |
| 灰度发布 | 模块 A/B 测试 | 新模块只导流一部分流量 |
这个对照不是偶然的——Modular RAG 本质上就是”RAG 管线的微服务化”。理解了这个对照,就能把微服务领域的成熟实践(灰度、熔断、链路追踪)直接搬到 RAG 管线上。
Modular RAG 的两个反模式
在实践中,Modular RAG 有两个常见反模式需要注意:
反模式一:过度模块化。把每个小功能都拆成模块,导致模块数量爆炸、接口复杂度飙升。正确做法是只在需要替换或独立优化的地方拆模块。如果一个函数永远不会被替换,硬编码在管线里反而更清晰。
反模式二:忽视模块间数据契约。每个模块的输入/输出格式就是模块间的”数据契约”。如果不显式定义契约(比如用 Pydantic model 或 JSON Schema),模块替换时就会因为格式不匹配而崩溃。WeKnora 用 Go interface 隐式定义了契约,但在 Python 生态中更推荐用 Pydantic 显式定义。
Modular RAG 是工程化的 Advanced RAG。如果你已经在做 Advanced RAG,Modular 是自然演进一步——把硬编码的优化逻辑拆成可插拔模块。
模式 4:Graph RAG
一句话
在传统检索基础上叠加知识图谱——不只查文档的”内容相似度”,还通过实体关系链查”结构关联性”,让间接相关的内容也能被找到。
日常类比
传统检索是查”和我的问题长得像的文档”——像在图书馆按主题分类找书。Graph RAG 多了一步:查完书之后,还翻这本书的”参见也”引用、作者的其他著作、同一主题的相关条目。这些间接关联的文档,传统检索永远找不到——因为它们和你问题的文本不相似,但逻辑上高度相关。
具体例子:你问”微信支付的技术架构”。传统检索找到直接描述微信支付架构的文档。Graph RAG 还能通过”微信支付 → 依赖 → 风控系统 → 共享组件 → 灰度发布框架”这条关系链,找到灰度发布框架的文档——它和”微信支付”文本不相似,但理解架构时不可或缺。
架构与数据流
flowchart TD
Q[用户查询] --> E1[实体抽取<br>从 query 中识别关键实体]
E1 --> SE[实体链接<br>消歧 + 对齐到图谱实体]
SE --> R1[向量检索 Top-K]
SE --> R2[BM25 检索]
SE --> R3[图谱遍历<br>实体 → 关系 → 邻居实体]
R3 --> G1[1 跳邻居]
R3 --> G2[2 跳邻居<br>可选,谨慎使用]
R1 --> F[RRF 融合]
R2 --> F
G1 --> F
G2 --> F
F --> RK[Rerank]
RK --> C[拼接上下文<br>含实体关系描述]
C --> L[LLM 生成]
L --> A[答案]
知识图谱构建管线
Graph RAG 的前置条件是已有知识图谱。图谱构建本身是重工程:
flowchart LR
D[原始文档] --> EE[实体抽取<br>LLM/NER]
EE --> RE[关系抽取<br>LLM/RE模型]
RE --> ED[实体消歧<br>同名合并/指代消解]
ED --> KG[知识图谱存储<br>Neo4j/NetworkX]
| 步骤 | 方法 | 成本 | WeKnora 方案 |
|---|---|---|---|
| 实体抽取 | LLM prompting / NER 模型 | 高(LLM 调用) | PMI 实体关系推理 |
| 关系抽取 | LLM prompting / RE 模型 | 高 | 统计共现 + PMI 打分 |
| 实体消歧 | 字符串相似度 + LLM 判断 | 中 | 基于上下文的消歧 |
| 图谱存储 | 属性图数据库 / 内存图 | 中 | NetworkX 内存图 |
WeKnora 的图谱路用 PMI(点互信息) 而非 LLM 做关系抽取——成本更低但粒度更粗。这是设计取舍:用统计方法替代 LLM,牺牲关系类型丰富度换取构建速度。详见 精读: WeKnora 和 技术挑战 第 4 条”知识图谱构建与维护成本”
微软 GraphRAG 方案
微软 2024 年开源的 GraphRAG 采用了不同策略:
- 用 LLM 从文档中抽取实体和关系(成本高但质量高)
- 对图谱做社区检测(Leiden 算法),生成每个社区的摘要
- 查询时先匹配社区摘要,再在社区内做细粒度检索
这个方案适合全局性摘要类查询(”这个数据集整体讲了什么”),而传统 RAG 适合局部细节查询(”某段代码怎么调用的”)。两者互补。
伪代码
def graph_rag(query, vector_db, graph_db, llm, top_k=5, max_hops=2):
# 1. 从 query 中抽取实体
entities = extract_entities(query, llm) # ["微信支付", "技术架构"]
# 2. 传统检索(向量 + BM25)
vec_chunks = vector_db.similarity_search(embed(query), k=top_k)
bm25_chunks = bm25_search(query, k=top_k)
# 3. 图谱遍历
graph_chunks = []
for entity in entities:
# 1 跳:entity → 关系 → 邻居
neighbors_1hop = graph_db.get_neighbors(entity, hop=1)
for neighbor in neighbors_1hop:
graph_chunks.extend(
vector_db.search_by_entity(neighbor, k=3)
)
# 2 跳(可选)
if max_hops >= 2:
neighbors_2hop = graph_db.get_neighbors(entity, hop=2)
for neighbor in neighbors_2hop:
graph_chunks.extend(
vector_db.search_by_entity(neighbor, k=2)
)
# 4. RRF 融合三路
fused = rrf_fuse(
[vec_chunks, bm25_chunks, graph_chunks],
k=60
)
# 5. Rerank + 生成
reranked = rerank(query, fused, top_n=3)
context = "\n".join([c.text for c in reranked])
answer = llm.generate(f"基于以下内容回答:\n{context}\n问题:{query}")
return answer
优势
- 覆盖间接关联——传统检索的盲区
- 多跳推理基础——”A 的发明者还写了什么”这类查询
- 实体关系可解释——答案引用链可追溯
- 全局摘要能力(微软方案)——传统 RAG 做不到
劣势与踩坑
| 坑 | 为什么 | 后果 |
|---|---|---|
| 图谱构建成本高 | LLM 抽取实体/关系,每篇文档至少 2 次 LLM 调用 | 大规模语料构建慢且贵 |
| 图谱稀疏 | 小语料库中实体共现不够,图谱边很少 | 图谱路退化为空结果 |
| 实体消歧难 | “苹果”是水果还是公司? | 关系链接错误,检索噪声 |
| 图谱维护 | 文档更新后图谱需要增量更新 | 维护是持续工程 |
| 2 跳邻居噪声爆炸 | 2 跳后邻居数量指数增长 | 引入大量无关内容 |
代表实现
- WeKnora 知识图谱路(PMI 实体关系)
- 微软 GraphRAG(LLM 抽取 + 社区摘要)
- cognee ECL 管线(Extract-Cognify-Load)—— 详见 精读: cognee
- graphiti 时序知识图谱 —— 详见 精读: graphiti
何时选用
- 实体关系密集的领域(医疗、法律、金融、企业知识库)
- 需要多跳推理的查询(”A → B → C”链条式问题)
- 已有知识图谱或有能力构建
- 文档量大(> 10K 篇),图谱才有足够密度
Graph RAG 的三种构建策略对比
构建知识图谱有三种主流策略,各有适用场景:
策略一:LLM 驱动抽取(微软 GraphRAG 采用)
- 方法:对每篇文档调用 LLM,让 LLM 识别实体和关系
- 优势:关系类型丰富(”发明”、”依赖”、”隶属于”等),质量高
- 劣势:成本极高(每篇文档 2-3 次 LLM 调用),速度慢
- 适合:文档量 < 10K 篇,对图谱质量要求高,预算充足
策略二:统计共现抽取(WeKnora 采用)
- 方法:统计实体在文档中的共现频率,用 PMI(点互信息)衡量关联强度
- 优势:成本极低(无需 LLM 调用),构建速度快
- 劣势:关系类型只有”共现”一种,无法区分”依赖”和”对立”等语义关系
- 适合:文档量大(> 100K 篇),需要快速构建,对关系类型丰富度要求不高
策略三:混合抽取(cognee 采用)
- 方法:先用统计方法快速构建骨架,再用 LLM 对高频实体对做精细关系分类
- 优势:兼顾成本和质量——大部分边用统计方法,少量关键边用 LLM 精化
- 劣势:工程复杂度高——需要维护两套抽取管线和合并逻辑
- 适合:中等规模文档量,既需要速度又需要关系类型丰富度
选择建议:如果文档量在一万篇以下且预算允许,直接用 LLM 驱动;如果文档量超过十万篇,先用统计共现跑起来,再按需用 LLM 精化关键区域。
Graph RAG 与向量检索的互补性
Graph RAG 不是要替代向量检索,而是与向量检索互补。两者覆盖的查询类型几乎不重叠:
| 查询类型 | 向量检索 | 图谱检索 | 原因 |
|---|---|---|---|
| “这个函数怎么用” | 强 | 弱 | 语义相似度直接命中 |
| “ECONNREFUSED 错误怎么处理” | 中 | 弱 | 需要精确关键词匹配 |
| “A 依赖了哪些组件” | 弱 | 强 | 需要关系遍历 |
| “A 和 B 的共同上级” | 极弱 | 强 | 需要多跳关系推理 |
| “这个数据集整体讲了什么” | 中 | 强 | 图谱社区摘要更擅长 |
正因为互补,WeKnora 选择三路全走——向量 + BM25 + 图谱各覆盖不同的查询类型,用 RRF 融合后几乎不存在”检索不到”的盲区。这种”宁可多查不可漏查”的哲学,和搜索引擎的”召回优先再精排”一脉相承。
Graph RAG 和 Memory 中的 Temporal Graph 模式有交叉——Graphiti 的时序知识图谱既可服务于 Agent 记忆也可服务于 RAG。详见 Memory 与 RAG 边界 和 记忆设计模式目录
模式 5:Agentic RAG
一句话
LLM 不只是生成器,还是检索的编排者——Agent 在工具循环中自主决定何时检索、查什么、结果够不够、要不要换策略,而非按固定管线执行。
日常类比
固定管线 RAG = 流水线工人——按 SOP 操作,拿到原材料就加工,不管原材料质量。Agentic RAG = 资深研究员——他会先想”这个问题需要查哪些资料”,查完第一轮后判断”信息不够,换个角度再查”,查到足够后才写报告。关键是:没人告诉他要查几轮,他自己判断。
更精确的类比边界:研究员的”自主判断”不是无限的——他有时间预算(token 限制)、有能力上限(LLM 推理能力)、有工具清单(可调用的数据源)。超出任何一个约束,判断就会出错。
架构与数据流——ReAct 循环
Agentic RAG 的核心是 ReAct(Reasoning + Acting)循环:
flowchart TD
Q[用户查询] --> TH[Thought 1<br>LLM 思考:需要什么信息?]
TH --> ACT1{Action 1<br>选择工具}
ACT1 -->|retrieve| R1[检索知识库 A]
ACT1 -->|web_search| W1[搜索互联网]
ACT1 -->|calculator| C1[计算]
R1 --> OBS1[Observation 1<br>检索结果]
W1 --> OBS1
C1 --> OBS1
OBS1 --> TH2[Thought 2<br>LLM 判断:信息够不够?]
TH2 -->|不够| ACT2{Action 2<br>选择工具}
ACT2 -->|retrieve| R2[检索知识库 B<br>或改写 query]
ACT2 -->|finish| ANS[生成答案]
R2 --> OBS2[Observation 2]
OBS2 --> TH3[Thought 3<br>LLM 判断:现在够了]
TH3 -->|够了| ANS
关键能力:查询分解
Agentic RAG 最突出的能力是查询分解——把一个复杂问题自主拆成多个检索动作:
| 用户问题 | 固定管线 | Agentic RAG |
|---|---|---|
| “对比 React 和 Vue 的性能” | 一次检索”React Vue 性能对比” | Thought→ 分别检索 React 性能数据、Vue 性能数据 → 对比生成 |
| “我们公司有类似竞品 X 的功能吗” | 一次检索”竞品 X” | Thought→ 检索竞品 X 的功能列表 → 逐个检索公司产品是否有对应功能 → 汇总 |
| “这个 bug 可能和哪个模块有关” | 一次检索 bug 描述 | Thought→ 检索 bug 症状 → 匹配模块 → 检索模块近期变更 → 定位 |
LangChain/LangGraph 实现
from langchain.agents import create_tool_calling_agent
from langchain.tools.retriever import create_retriever_tool
from langchain_core.prompts import ChatPromptTemplate
# 1. 把 RAG 检索器包装成 Agent 工具
retriever_tool_A = create_retriever_tool(
retriever=weknora_retriever, # WeKnora API
name="search_internal_kb",
description="搜索公司内部知识库,含产品文档/技术方案/运营数据"
)
retriever_tool_B = create_retriever_tool(
retriever=product_docs_retriever,
name="search_product_docs",
description="搜索产品手册,含API文档/使用指南"
)
# 2. Agent 自主决定何时调用哪个工具、调几次
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个研究助理。先用内部知识库查,不够再用产品手册查。"),
("human", "{input}"),
("placeholder", "{agent_scratchpad}"),
])
agent = create_tool_calling_agent(
llm=llm,
tools=[retriever_tool_A, retriever_tool_B, web_search_tool],
prompt=prompt
)
关键行:create_retriever_tool 把 RAG 变成 Agent 的一个工具选项——Agent 可以选择不检索(如果问题已知)、检索一次、或多次检索不同知识库。
Dify Agent 节点实现
Dify 的 Workflow 模式支持在可视化 DAG 中插入”知识检索”节点,配合”条件判断”节点可实现 Corrective RAG:
- 检索节点 → 返回结果
- 条件判断节点 → “相关性 > 阈值?”
- 是 → 生成;否 → 重写 query → 再检索
WeKnora 与 Agentic RAG 的关系
WeKnora 本身是固定管线(EventManager 派发,三路全走),但有两个 Agentic 集成点:
cmd/Agent 对话入口:流式 SSE,可以看作”把 WeKnora 整体作为一个工具暴露给 Agent”mcp-server/目录:通过 MCP 协议让任意 Agent 框架调用 WeKnora 检索
这意味着 WeKnora 定位是”检索引擎”而非”Agent 平台”——Agentic 编排由外部 Agent 框架负责,WeKnora 只提供高质量的检索能力。详见 Agent 与 RAG 平台集成 和 精读: WeKnora
伪代码(ReAct 循环)
def agentic_rag(query, llm, tools, max_iterations=5):
messages = [{"role": "user", "content": query}]
scratchpad = [] # 记录 Thought/Action/Observation
for i in range(max_iterations):
# Thought: LLM 思考下一步
thought = llm.generate(
f"已有信息:{scratchpad}\n下一步做什么?"
)
scratchpad.append(f"Thought: {thought}")
# Action: 选择并执行工具
action, tool_input = parse_action(thought)
if action == "finish":
# LLM 认为信息够了,生成答案
answer = llm.generate(
f"基于以下信息回答:{scratchpad}\n问题:{query}"
)
return answer
# 执行工具
tool = tools[action] # 如 "search_internal_kb"
observation = tool.run(tool_input)
scratchpad.append(f"Action: {action}({tool_input})")
scratchpad.append(f"Observation: {observation}")
# 超过最大迭代次数,强制生成
return llm.generate(f"基于有限信息回答:{scratchpad}\n问题:{query}")
优势
- 灵活适应未知查询——无需预设检索策略
- 查询分解——复杂问题自动拆成多步检索
- 自纠偏——检索结果不够时自主调整
- 多工具协作——同时用知识库、互联网、计算器
劣势与踩坑
| 坑 | 为什么 | 后果 |
|---|---|---|
| 延迟不可预测 | 每次循环 = 1 次 LLM + 1 次检索 | 复杂问题可能 5+ 轮循环 |
| 成本线性增长 | 每轮都消耗 LLM token | 生产环境需要严格成本控制 |
| Agent “忘了”检索 | LLM 可能直接用训练知识回答 | 产生幻觉,绕过知识库 |
| 循环失控 | LLM 可能一直判断”不够” | 需要硬性 max_iterations 上限 |
| 调试困难 | 非确定性执行路径 | 同一问题可能走不同检索路径 |
代表实现
- LangChain Agent + Retriever Tool
- LangGraph ReAct 模板
- Dify Agent 节点
- AutoGPT 知识库调用
何时选用
- 查询高度多样,无法预设检索策略
- 需要多数据源协作(内部知识库 + 互联网 + 数据库)
- 对延迟/成本不敏感(研究/分析场景)
- 需要自纠偏能力(合规、医疗等高准确率场景)
Agentic RAG 的核心 trade-off 是灵活性 vs 可控性。固定管线可控但死板,Agent 灵活但不可控。实际落地往往是”半 Agentic”——部分环节 Agent 决策,部分环节固定管线。
Agentic RAG 的三种落地形态
实际落地中,”Agent 编排检索”有三种程度不同的形态:
形态一:检索即工具(最轻量)
- Agent 把 RAG 检索器当作一个工具调用,和 web_search、calculator 并列
- Agent 决定”要不要调”和”调几次”,但每次调用的检索策略是固定的
- 代表:LangChain
create_retriever_tool、WeKnora MCP Server - 适用:已有高质量 RAG 引擎(如 WeKnora),只需要让 Agent 决定何时调用
形态二:检索策略可调(中等)
- Agent 不仅决定”要不要调”,还能调整检索参数(top_k、检索路、相似度阈值)
- 例如:第一次用语义检索 broad search(top_k=20),发现结果太散,第二次切换为精确关键词检索(top_k=5)
- 代表:Dify Agent 节点 + 参数传递
- 适用:查询多样性高,不同查询需要不同检索策略
形态三:检索管线可编排(最重)
- Agent 不只调参数,还能动态编排检索管线——先查知识库 A,不够查知识库 B,再不够调 web search,最后用 LLM 判断是否足够
- 这本质上是让 Agent 成为一个”检索管线生成器”
- 代表:LangGraph 动态图、AutoGPT
- 适用:研究型场景,查询极其复杂且不可预测
三种形态的成本递增、灵活性递增、可控性递减。生产环境建议从形态一开始,按需升级到形态二。形态三只在离线研究场景使用。
Agentic RAG 的成本估算
假设一次 LLM 调用成本 0.01 元,一次向量检索成本 0.001 元,一次 Rerank 成本 0.002 元:
| 场景 | 固定管线 | Agentic (2轮) | Agentic (5轮) | Multi-hop (3跳) |
|---|---|---|---|---|
| LLM 调用次数 | 1 | 3 | 6 | 7 |
| 检索次数 | 1 | 2 | 5 | 3 |
| Rerank 次数 | 1 | 2 | 5 | 3 |
| 总成本 | ~0.013 元 | ~0.036 元 | ~0.067 元 | ~0.076 元 |
| 倍率 | 1x | ~2.8x | ~5.2x | ~5.8x |
结论:Agentic RAG 的成本通常是固定管线的 3-6 倍。在成本敏感的生产环境中,需要设置严格的 token 预算和最大迭代次数上限。
模式 6:Multi-hop Agentic RAG
一句话
Agent 不只多轮检索——每轮检索的结果是下一轮检索的输入线索,形成推理链:查到 A → 从 A 中提取线索 → 用线索查 B → 从 B 中提取线索 → 用线索查 C → 综合生成。
日常类比
单跳 Agentic RAG = 研究员查一轮资料就写报告。Multi-hop = 研究员做深度调查——第一轮查到”这个项目的负责人是张三”,第二轮查”张三还负责哪些项目”,第三轮查”那些项目的技术栈”,三轮之后才能回答”这个项目可能用了什么技术栈”。
关键区别:后一轮的检索词来自前一轮的检索结果,而不是来自原始问题。这使得推理链越长,和原始问题的语义距离越远——传统检索完全无法覆盖。
架构与数据流
flowchart TD
Q[用户查询] --> H1[Hop 1: 检索<br>query = 原始问题]
H1 --> R1[结果集 1]
R1 --> E1[提取线索<br>LLM 从结果中提取<br>下一步检索词]
E1 --> H2[hop 2: 检索<br>query = 提取的线索]
H2 --> R2[结果集 2]
R2 --> E2[提取线索]
E2 --> H3[hop 3: 检索<br>query = 新线索]
H3 --> R3[结果集 3]
R3 --> SYN[综合推理<br>LLM 整合所有 hop 结果]
SYN --> A[答案]
style H1 fill:#e8f4e8
style H2 fill:#e8e8f4
style H3 fill:#f4e8e8
伪代码
def multi_hop_rag(query, llm, retriever, max_hops=3):
all_evidence = []
current_queries = [query] # 初始检索词就是原始问题
for hop in range(max_hops):
hop_results = []
for q in current_queries:
chunks = retriever.retrieve(q, top_k=5)
hop_results.extend(chunks)
all_evidence.extend(hop_results)
# LLM 从当前结果中提取下一步线索
next_queries = llm.generate(
f"基于以下检索结果,提取还需要进一步查找的问题:\n"
f"原始问题:{query}\n"
f"已找到的信息:{hop_results}\n"
f"还缺什么信息?"
)
current_queries = parse_queries(next_queries)
if not current_queries:
break # LLM 认为信息已足够
# 综合所有 hop 的证据生成答案
all_context = "\n".join([e.text for e in all_evidence])
answer = llm.generate(
f"基于以下所有证据回答:\n{all_context}\n问题:{query}"
)
return answer
典型查询模式
| 查询类型 | 跳数 | 推理链示例 |
|---|---|---|
| 链式追溯 | 2-3 | “X 的作者 → 作者的其他论文 → 论文引用的方法” |
| 对比分析 | 2-4 | “A 的特性 → B 的特性 → A vs B 差异 → 差异的根因” |
| 影响分析 | 3-5 | “变更 X → X 影响的模块 → 模块依赖的服务 → 服务的下游” |
| 原因推断 | 2-3 | “异常现象 → 可能原因列表 → 各原因的验证证据” |
误差级联问题
Multi-hop 最核心的工程挑战是误差级联——每一跳都可能出错,错误沿推理链传播放大。
| 跳数 | 单跳准确率 | 端到端准确率(乘积) | 风险 |
|---|---|---|---|
| 1 | 90% | 90% | 低 |
| 2 | 90% | 81% | 中 |
| 3 | 90% | 73% | 较高 |
| 4 | 90% | 66% | 高 |
| 5 | 90% | 59% | 很高 |
缓解策略:
- 每跳验证:每跳检索后 LLM 判断结果是否相关,不相关则重试
- 多路径并行:同一跳拆成多个子查询并行检索,多数投票取结果
- 回溯机制:后续跳发现矛盾时,回退到前面跳重新检索
- 人类在环:关键跳点暂停请人确认
优势
- 唯一能处理”线索链”类查询的模式
- 推理过程可解释——每一跳都有明确输入输出
- 发现间接关联——传统检索的盲区
劣势与踩坑
| 坑 | 为什么 | 后果 |
|---|---|---|
| 延迟线性增长 | 每跳 = 1 次检索 + 1 次 LLM | 3 跳可能 10s+ |
| 误差级联 | 每跳准确率 < 100% | 端到端准确率指数衰减 |
| 中间线索提取错误 | LLM 从结果中提取的线索可能偏 | 后续跳全部偏掉 |
| 难以评估 | 端到端评估无法区分哪跳出错 | 调优困难 |
代表实现
- LangGraph 多步推理图
- IRCoT(Interleaving Retrieval with Chain-of-Thought)
- Flare(Active Retrieval Augmented Generation)
- Dify Workflow 循环节点
何时选用
- 查询本质上是多跳推理(链式追溯、影响分析)
- 对延迟容忍度高(离线分析、深度研究)
- 有完善的每跳验证机制
- 单跳准确率 > 95%(否则级联后不可用)
Agent 框架中的 Dynamic Workflow 场景可实现此模式,详见 A 线 · Agent 框架
Multi-hop RAG 的两个实战案例
案例一:竞品功能对标
用户问题:”我们产品有没有类似 Slack 的 thread 功能?”
推理链:
- 第一跳:检索”Slack thread 功能介绍” → 了解到 thread 是按话题归组消息的功能
- 第二跳:提取线索”按话题归组消息” → 检索公司产品中”消息归组”、”话题讨论”相关功能 → 找到”频道子话题”功能
- 第三跳:检索”频道子话题”的详细文档 → 确认功能对等性 → 生成对比结论
这个案例体现了 Multi-hop 的核心价值:用户问的是”我们有没有类似 X 的功能”,但”X”和”我们的功能”用词不同,无法一步检索命中。需要先理解 X 是什么,再转化为我们系统的概念,最后检索确认。
案例二:代码依赖影响分析
用户问题:”修改 UserService 的认证逻辑会影响哪些下游服务?”
推理链:
- 第一跳:检索”UserService 认证逻辑” → 了解该服务被哪些模块调用
- 第二跳:提取线索”OrderService、PaymentService、NotificationService” → 逐个检索这些服务的认证依赖 → 了解调用方式
- 第三跳:检索这些服务的外部调用方 → 评估影响范围 → 生成影响分析报告
这个案例体现了 Multi-hop 的风险:如果第一跳遗漏了某个调用方(比如通过反射调用的隐式依赖),后续所有跳都基于不完整的信息,结论就有盲区。缓解方法是在第一跳用多种检索方式并行(向量 + BM25 + 图谱),最大化召回率。
Multi-hop 与 Graph RAG 的关系
Multi-hop RAG 和 Graph RAG 都能处理”需要间接关联信息”的查询,但机制不同:
| 维度 | Graph RAG | Multi-hop RAG |
|---|---|---|
| 关联发现方式 | 预先构建的图谱,查询时遍历 | 实时检索,每跳从结果中提取线索 |
| 前置条件 | 需要提前构建知识图谱 | 不需要图谱,但需要高质量检索器 |
| 延迟 | 低(图谱遍历快) | 高(每跳一次 LLM + 一次检索) |
| 灵活性 | 低(只能查图谱已有的关系) | 高(可以查任意关联) |
| 准确率 | 高(图谱关系是预先验证的) | 中(每跳可能出错) |
简单说:Graph RAG 是”提前修好高速公路,查询时直接上高速”,Multi-hop 是”没有高速公路,每一步都靠导航探索”。有高速公路当然更快更稳,但修路成本高,而且到不了没修路的地方。
Agent 框架中的 Dynamic Workflow 场景可实现此模式,详见 A 线 · Agent 框架
模式演进光谱
flowchart LR
N[Naive RAG<br>单路检索] --> ADV[Advanced RAG<br>检索前后优化]
ADV --> MOD[Modular RAG<br>可插拔管线]
MOD --> G[Graph RAG<br>图谱增强]
MOD --> A[Agentic RAG<br>Agent 决定检索]
A --> M[Multi-hop<br>多轮检索推理]
G --> A
style N fill:#f9f9f9
style ADV fill:#e8f4e8
style MOD fill:#e8f4e8
style G fill:#e8f4e8
style A fill:#e8e8f4
style M fill:#e8e8f4
越往右:检索质量潜力越高,延迟/成本越大,工程复杂度越高。
演进的核心逻辑:
- Naive → Advanced:不改架构,在前后插入优化模块(投入产出比最高)
- Advanced → Modular:把硬编码优化拆成可插拔模块(工程化升级)
- Modular → Graph:在检索路中增加图谱引擎(覆盖间接关联)
- Modular → Agentic:把固定编排换成 LLM 编排(灵活性飞跃)
- Agentic → Multi-hop:让 Agent 做链式推理(最深但最慢)
从 Naive 到 Agentic 的渐进升级路径
从 Naive RAG 升级到 Agentic RAG 不是一步到位——每一步解决一类问题,每一步都有明确的 ROI。
| 阶段 | 起点 → 终点 | 核心改动 | 预期提升 | 改动量 | 前置条件 |
|---|---|---|---|---|---|
| 1 | Naive → +Rerank | 检索后加交叉编码器精排 | 召回质量 +15-30% | 加 1 个模块 | 有 Rerank 模型 |
| 2 | +Rerank → +Query Rewriting | 检索前加查询改写 | 长尾查询 +10-20% | 加 1 个模块 | LLM API |
| 3 | +QR → +Hybrid | 加 BM25 双路检索 | 精确关键词 +20-40% | 加 1 路检索 | BM25 索引 |
| 4 | +Hybrid → +RRF Fusion | 多路排名融合 | 多路互补 +5-15% | 加融合逻辑 | ≥2 路检索 |
| 5 | +RRF → Modular | 拆成可插拔模块 | 工程可维护性 | 重构代码 | 已有 3+ 模块 |
| 6 | Modular → +Graph | 加知识图谱检索路 | 间接关联 +10-20% | 构建图谱 + 加检索路 | 有实体/关系 |
| 7 | +Graph → Agentic | LLM 编排检索决策 | 复杂查询 +20-50% | 换编排层 | Agent 框架 |
| 8 | Agentic → Multi-hop | 加推理链和多跳 | 链式查询 +30-60% | 加跳转逻辑 | 每跳验证 |
渐进升级的三个关键决策点
在升级路径上有三个关键决策点,选错方向会导致返工:
决策点一:是否加图谱路?(阶段 6 分叉)
加图谱路的前提条件是”你的领域实体关系密集”。判断方法:
- 文档中是否频繁出现人名/组织名/产品名/技术名词等实体?→ 如果实体密度 < 每篇文档 3 个,图谱太稀疏不值得
- 用户查询是否经常涉及”X 和 Y 的关系”、”X 影响了谁”这类关系型问题?→ 如果 < 10% 的查询是关系型,图谱路 ROI 低
- 是否有能力持续维护图谱?→ 图谱不是建一次就完,文档更新后图谱需要增量更新
如果以上三个条件都不满足,跳过 Graph RAG,直接从 Modular 升级到 Agentic。
决策点二:是否上 Agentic?(阶段 7 分叉)
上 Agentic 的前提条件是”你的查询足够多样,固定管线覆盖不了”。判断方法:
- 查询模式是否 > 5 种且差异大?→ 如果只有 2-3 种查询模式,固定管线 + 条件分支足够
- 是否需要多数据源协作?→ 如果只有一个知识库,Agentic 的”自主选择数据源”能力无用武之地
- 延迟和成本预算是否允许?→ Agentic 通常 3-6 倍成本,生产环境需要确认预算
如果以上条件不满足,停留在 Modular + Graph(WeKnora 当前状态)就是最优解。
决策点三:是否上 Multi-hop?(阶段 8 分叉)
上 Multi-hop 的前提条件是”你的查询本质上是链式推理”。判断方法:
- 用户是否经常问”X 的上游/下游”、”X 影响了谁”、”X 的历史演变”这类链式问题?
- 单跳检索准确率是否 > 95%?→ 如果基础检索质量不够,Multi-hop 的误差级联会让结果更差
- 是否能接受 10 秒以上的延迟?→ 3 跳 Multi-hop 典型延迟 10-30 秒
大多数生产场景不需要 Multi-hop。它只在深度研究、代码审计、合规溯源等特定领域有价值。
升级路径的 WeKnora 具体路线
基于以上决策点和 WeKnora 的现状,推荐两条贡献路线:
路线 A:深化固定管线(推荐,投入产出比高)
- 优化 Rerank 模型——当前复合 Rerank 已有,可尝试领域微调
- 增加查询改写——当前无内建 query rewriting,是明显短板
- 优化图谱路——PMI 关系抽取粒度可提升,混合 LLM 精化高频实体对
- 降低三路延迟——当前三路并行仍有延迟叠加,可探索早退机制
路线 B:打通 Agentic 集成(战略价值高但工程量大)
- 完善 MCP Server——让 WeKnora 可被 LangChain/LangGraph/Claude Code 直接调用
- 提供检索策略参数化——让外部 Agent 能调整 top_k、检索路、相似度阈值
- 端到端评估——建立”Agent + WeKnora”benchmark,量化 Agentic 模式效果
每阶段的验收标准
| 阶段 | 评估指标 | 目标值 | 评估方法 |
|---|---|---|---|
| 1 (+Rerank) | MRR / Hit Rate | 较 Naive +15% | RAG 评估方法论 |
| 2 (+QR) | 长尾查询召回率 | +10% | 按查询频次分桶评估 |
| 3 (+Hybrid) | 精确关键词查询准确率 | +20% | 关键词测试集 |
| 4 (+RRF) | 多路融合后 F1 | 优于单路最优 | 融合 vs 单路 A/B |
| 5 (Modular) | 模块替换后管线正确性 | 100% | 模块替换测试 |
| 6 (+Graph) | 多跳查询准确率 | +10% | 多跳测试集 |
| 7 (Agentic) | 复杂查询准确率 | +20% | 对比固定管线 |
| 8 (Multi-hop) | 链式推理完成率 | >80% | 端到端评估 |
编排方式对比
| 维度 | WeKnora 固定管线 | Dify Workflow | LangGraph Agent |
|---|---|---|---|
| 编排方式 | EventManager 事件总线 | 可视化拖拽 DAG | Python 代码图 |
| 检索决策 | 固定三路全走 | 节点条件分支 | LLM 决定是否调用 |
| 延迟 | 中–高(三路并行) | 中(按 DAG 执行) | 可变(循环次数不定) |
| 适合场景 | 企业知识库 “最大化召回” | 快速搭应用原型 | 复杂推理 / 研究 |
| 扩展成本 | 改 Go plugin | 拖新节点 | 改 Python 图 |
| 幻觉控制 | Rerank 兜底 | 可加判断节点 | Agent 自检 |
| 多跳能力 | 无(单轮管线) | 有(循环节点) | 有(图循环) |
| RAG 模式 | Advanced + Graph | Advanced → Agentic | Agentic → Multi-hop |
关键 Trade-off
固定管线 vs Agent 编排
flowchart TD
Q[用户查询] --> D{编排方式?}
D -->|固定管线| F[三路全查 → RRF → Rerank → 生成]
D -->|Agent 编排| A[LLM 判断 → 选择数据源 → 检索 → 够了?]
A -->|不够| A
A -->|够了| G[生成答案]
F --> R[结果]
G --> R
| 固定管线(WeKnora) | Agent 编排 | |
|---|---|---|
| 优势 | 可预测延迟、确定性结果 | 灵活、可适应未知查询 |
| 劣势 | 无法动态调整策略 | 延迟/成本不可控 |
| 何时选 | 场景明确、需要 SLA 保证 | 查询多样、需要推理 |
Hybrid RAG 的 WeKnora 参数选择(为何这么设)
| 参数 | WeKnora 值 | 设计意图 [已有] |
|---|---|---|
| RRF k | 60 | 论文经验最优——平滑排名差异 |
| 向量权重 | 0.7 | 语义理解为主信号 |
| BM25 权重 | 0.3 | 精确匹配为辅助 |
| Rerank 模型分 | 0.6 | 模型判断为主 |
| Rerank 基础分 | 0.3 | 检索分数兜底 |
| Rerank 来源分 | 0.1 | 文档来源可信度 |
与 5 项目横评的映射
各项目默认支持的 RAG 模式和升级潜力:
| 项目 | 默认模式 | 支持的模式 | 升级到 Agentic 的路径 | 限制 |
|---|---|---|---|---|
| WeKnora | Advanced + Graph(固定管线) | Naive → Advanced → Modular → Graph | 通过 MCP/API 被外部 Agent 调用 | 无内建 Agent 编排 |
| Dify | Advanced(可配置) | Naive → Advanced → Modular → Agentic | 原生 Agent 节点 + Workflow | Agent 调试体验待优化 |
| RAGFlow | Advanced(DeepDoc 为主) | Naive → Advanced → Modular | API 暴露给外部 Agent | 无内建 Agent、图谱 |
| AnythingLLM | Naive → Hybrid | Naive → Advanced | Agent 模式(较简单) | Agent 能力有限 |
| FastGPT | Advanced(Hybrid) | Naive → Advanced → Modular → Agentic | Workflow 编排(类 Dify) | 图谱路缺 |
模式 × 项目矩阵
| 模式 | WeKnora | Dify | RAGFlow | AnythingLLM | FastGPT |
|---|---|---|---|---|---|
| Naive RAG | ✓ | ✓ | ✓ | ✓ | ✓ |
| Advanced RAG | ✓ | ✓ | ✓ | ○ | ✓ |
| Modular RAG | ✓ | ✓ | ✓ | ✗ | ✓ |
| Graph RAG | ✓ | ✗ | ✗ | ✗ | ✗ |
| Agentic RAG | ○(MCP) | ✓ | ○(API) | ○ | ✓ |
| Multi-hop RAG | ✗ | ○ | ✗ | ✗ | ○ |
✓ = 原生支持 · ○ = 通过外部集成 · ✗ = 不支持
5 项目详细对比见 横评: RAG 知识库 WeKnora 架构精读见 精读: WeKnora 各项目精读见 精读: Dify / 精读: RAGFlow / 精读: AnythingLLM / 精读: FastGPT
Agentic RAG 实际落地形态
LangChain/LangGraph
见模式 5 中的伪代码示例。核心模式:create_retriever_tool 把 RAG 检索器包装为 Agent 工具,Agent 在 ReAct 循环中自主调用。
Dify Agent 节点
Dify 的 Workflow 模式支持在可视化 DAG 中插入”知识检索”节点,配合”条件判断”节点可实现 Corrective RAG:
- 检索节点 → 返回结果
- 条件判断节点 → “相关性 > 阈值?”
- 是 → 生成;否 → 重写 query → 再检索
WeKnora 固定管线(非 Agentic,但有 Agent 聊天入口)
WeKnora 本身是固定管线(EventManager 派发,三路全走),但 cmd/ 下有 Agent 对话入口(流式 SSE),可以看作”把 WeKnora 整体作为一个工具暴露给 Agent”。mcp-server/ 目录进一步证实了这个方向。
Corrective RAG / Self-RAG(自检式)
自检式 RAG 是 Agentic RAG 的一个重要子模式,值得单独说明。
一句话
检索后加一步”相关性判断”——如果检索结果不相关,重新生成 query 或切换数据源,而非直接生成。
架构
flowchart TD
Q[用户查询] --> R[检索]
R --> J{LLM 判断<br>结果是否相关?}
J -->|相关| G[生成答案]
J -->|不相关| Q2{如何纠偏?}
Q2 -->|Query Rewriting| QR[重写查询 → 再检索]
Q2 -->|换数据源| DS[切换到备用数据源 → 再检索]
Q2 -->|放弃| F[返回"我不知道"]
QR --> R
DS --> R
代表
- Self-RAG 论文(Asai et al. 2023)——在生成 token 级别插入反思标记
- CRAG 论文(Yan et al. 2024)——检索结果不相关时触发 web search 补偿
- LangGraph Corrective RAG 模板
与 WeKnora 关系
WeKnora 的复合 Rerank(0.6/0.3/0.1)在模型层面做了类似的”质量兜底”——Rerank 分数低的 chunk 会被降权,相当于”判断结果不够好 → 降低其影响”。但这不是 Agent 级别的自主纠偏,而是模型级别的静态过滤。
Corrective RAG 的三种纠偏策略
当检索结果被判为”不相关”时,有三种纠偏策略可以选择:
策略一:查询改写重检索 最常用的策略。LLM 分析原始查询和检索结果的偏差,重新生成更精确的查询词。例如用户问”熔断机制怎么配置”,检索结果全是关于保险行业的”熔断”——LLM 将查询改写为”微服务熔断器配置 Hystrix Sentinel”,再次检索命中技术文档。
这个策略的关键是改写不能偏离原始意图太远。如果改写后的查询和原始查询语义差异太大,虽然检索结果变了,但可能答非所问。实践中通常在改写 prompt 中加入约束:”保持原始问题意图不变,只调整检索关键词”。
策略二:切换数据源 当知识库中没有相关信息,但问题可能有互联网答案时,切换到 web search。典型场景:用户问”最新的 Python 3.13 有什么新特性”——内部知识库可能还没收录,但互联网上已有大量讨论。
这个策略的 trade-off 是:互联网信息质量参差不齐,需要额外的信任度评估。CRAG 论文建议对 web search 结果也做相关性判断,只采纳高置信度的信息。
策略三:诚实放弃 当所有纠偏策略都无法找到相关信息时,最好的做法是让 LLM 回答”根据知识库中的信息,我无法回答这个问题”,而不是基于不充分的证据猜测。
这个策略看似简单,实际上是最难正确实现的——因为 LLM 有强烈的”回答倾向”,即使信息不足也会试图给出答案。需要在 prompt 中明确指示:”如果信息不足以回答问题,必须明确说明,不要推测”。
Memory 与 RAG 在各模式中的角色
RAG 和 Agent Memory 虽然都是”给 LLM 补充信息”的机制,但在六种模式中扮演不同角色。理解这个区分,才能避免重复建设或遗漏关键能力。
两种信息补充机制的本质差异
RAG 从外部文档中检索信息——文档是静态的、可版本化的、多人共享的。RAG 回答的问题是”知识库中有什么”。
Memory 从交互历史中提取信息——记忆是动态的、个性化的、逐步积累的。Memory 回答的问题是”之前发生过什么、学到了什么”。
两者的重叠区域是”提炼后的知识”——比如 Agent 从多次交互中总结出”用户偏好用 TypeScript 而非 JavaScript”,这条知识既存在于 Memory 中,也可能被写入知识库成为 RAG 的数据源。详见 Memory 与 RAG 边界
六种模式中 Memory 的角色
| 模式 | Memory 的角色 | 原因 |
|---|---|---|
| Naive RAG | 无 | 管线无状态,不积累记忆 |
| Advanced RAG | 可选(用于查询改写) | 如果 Memory 记录了用户偏好,可用于个性化查询改写 |
| Modular RAG | 可选(作为模块之一) | Memory 模块可以插入管线,在检索前注入用户上下文 |
| Graph RAG | 互补(图谱 vs 记忆图) | 知识图谱是全局共享的,Memory 图是个性化的 |
| Agentic RAG | 重要(Agent 需要记忆) | Agent 的决策依赖历史经验——”上次查这个知识库效果不好” |
| Multi-hop RAG | 关键(推理链需要记忆) | 每跳的线索提取依赖前跳结果,短时 Working Memory 是必需的 |
关键洞察:越往 Agentic 方向走,Memory 越重要。Naive RAG 可以完全不需要 Memory,但 Agentic RAG 如果没有 Memory,Agent 就无法从历史经验中学习,每次都从零开始——这和”没有记忆的研究员”一样低效。
Memory-RAG 协同的最佳实践
实践中有三种协同模式:
协同模式一:Memory 辅助 RAG 检索
- Agent Memory 中记录了用户的领域偏好、历史查询模式
- 检索前先从 Memory 中提取用户上下文,用于个性化查询改写
- 例如:Memory 记录”用户是前端开发者”→ 查询”hooks”时改写为”React hooks”而非”Git hooks”
协同模式二:RAG 结果沉淀为 Memory
- 检索到的重要事实写入 Agent Memory,下次不用再检索
- 例如:第一次检索”公司 API 网关地址是 api.example.com”,记入 Memory → 下次直接从 Memory 读取
协同模式三:冲突检测与解决
- Memory 中的事实和 RAG 检索结果不一致时,触发冲突处理
- 例如:Memory 记录”配置文件在 /etc/app/config.yaml”,但 RAG 检索到文档说”配置文件已迁移到 ~/.app/config.yaml”→ 标记冲突,提示用户确认
- 这是 技术挑战 第 10 条”Memory 与 RAG 冲突”的具体场景
Memory 设计模式的详细目录见 记忆设计模式目录,特别是 Temporal Graph 模式与 Graph RAG 的交叉关系
对犀牛鸟竞赛的启示
- WeKnora 定位是”检索引擎”而非”Agent 平台” — 贡献方向应聚焦检索质量,而非重造 Agent 编排轮子
- MCP Server 是 Agentic 集成的桥 —
mcp-server/让 WeKnora 可被任意 Agent 框架调用,这是高价值贡献方向 - 评估 Agentic RAG 效果需要 benchmark — 当前社区缺少”Agent + WeKnora”端到端评估数据集,这是潜在贡献点
- 从 Naive 到 Advanced 的升级路径最值得贡献 — Rerank 优化、查询改写、多路融合调参,这些都是 WeKnora 已有但可提升的方向
- Graph RAG 是 WeKnora 的护城河 — 三路检索中图谱路是差异化最强的,但构建/维护成本也最高,降低成本是贡献方向
贡献具体路径见 竞赛指南: WeKnora 贡献 技术挑战全局视角见 技术挑战
模式选择决策树
根据场景特征快速选择合适的 RAG 模式:
flowchart TD
START[开始选择 RAG 模式] --> Q1{文档量级?}
Q1 -->|< 1K 篇| N[Naive RAG<br>够用,先跑起来]
Q1 -->|1K-100K 篇| Q2{查询复杂度?}
Q1 -->|> 100K 篇| Q2
Q2 -->|简单/单一| Q3{需要精确关键词匹配?}
Q2 -->|多样/复合| Q5{需要多数据源?}
Q3 -->|不需要| ADV1[Advanced RAG<br>向量 + Rerank]
Q3 -->|需要| ADV2[Advanced RAG<br>Hybrid + RRF + Rerank]
Q5 -->|不需要| Q6{涉及实体关系推理?}
Q5 -->|需要| Q7{延迟预算?}
Q6 -->|是| GRAPH[Graph RAG<br>图谱增强检索]
Q6 -->|否| MOD[Modular RAG<br>可配置管线]
Q7 -->|< 3s| AGENT1[Agentic RAG<br>形态一:检索即工具]
Q7 -->|3-10s| AGENT2[Agentic RAG<br>形态二:策略可调]
Q7 -->|> 10s| Q8{需要链式推理?}
Q8 -->|是| MHOP[Multi-hop Agentic RAG]
Q8 -->|否| AGENT3[Agentic RAG<br>形态三:管线可编排]
决策速查表
不想看流程图?用这张表快速判断:
| 你的场景 | 推荐模式 | 理由 |
|---|---|---|
| 个人知识库,文档 < 100 篇 | Naive | 任何优化都是过度工程 |
| 团队知识库,需要稳定回答 | Advanced (Hybrid + Rerank) | 性价比最高的生产配置 |
| 多团队共用,需要灵活配置 | Modular | 不同团队用不同模块组合 |
| 企业知识库,关系密集(法律/医疗/金融) | Graph | 实体关系是核心检索路径 |
| 研究助理,需要多源调查 | Agentic (形态二) | 自主决策何时查什么 |
| 深度分析,需要追踪因果链 | Multi-hop | 链式推理是核心需求 |
详细的项目级决策树见 RAG 平台决策树
各模式的评估方法选择
不同 RAG 模式需要不同的评估指标和评估方法。用错评估方法,会得出”高级模式不如 Naive”的错误结论——因为指标没有覆盖高级模式新增的能力维度。
评估指标与模式的对应关系
| 评估指标 | Naive | Advanced | Modular | Graph | Agentic | Multi-hop |
|---|---|---|---|---|---|---|
| Hit Rate (Top-K 命中率) | 必须 | 必须 | 必须 | 必须 | 必须 | 必须 |
| MRR (倒数排名均值) | 必须 | 必须 | 必须 | 必须 | 必须 | 必须 |
| Faithfulness (忠实度) | 必须 | 必须 | 必须 | 必须 | 必须 | 必须 |
| Answer Relevancy | 必须 | 必须 | 必须 | 必须 | 必须 | 必须 |
| Rerank 精度 | — | 必须 | 必须 | 必须 | 可选 | 可选 |
| 查询改写质量 | — | 必须 | 必须 | 可选 | 必须 | 必须 |
| 图谱覆盖率 | — | — | — | 必须 | 可选 | 可选 |
| 多跳完成率 | — | — | — | — | — | 必须 |
| Agent 决策准确率 | — | — | — | — | 必须 | 必须 |
| 端到端延迟 | 推荐 | 推荐 | 推荐 | 必须 | 必须 | 必须 |
| 每查询成本 | 可选 | 推荐 | 推荐 | 必须 | 必须 | 必须 |
各模式的评估陷阱
Naive RAG 的评估陷阱:用”简单问题”做测试集,Naive 和 Advanced 差距不大——因为简单问题本身就是 Naive 能处理的。必须加入”精确关键词查询”、”跨文档推理”、”模糊查询”三类难例,才能暴露 Naive 的短板。
Advanced RAG 的评估陷阱:Query Rewriting 可能改写过度——改写后的查询虽然检索效果好,但偏离了原始意图。必须评估”改写忠实度”:改写后的查询是否仍然表达用户的原始意图。
Graph RAG 的评估陷阱:图谱路召回的文档可能”间接相关但直接不相关”——通过关系链找到的文档和原始查询文本不相似,但逻辑上相关。传统的语义相似度指标会低估这类结果的价值。需要人工标注”间接相关性”来判断图谱路是否真正有帮助。
Agentic RAG 的评估陷阱:Agent 的执行路径不确定——同一问题可能走不同检索路径得到不同答案。必须用同一测试集多次运行,统计答案的一致性和准确率的方差。方差大说明 Agent 决策不稳定,需要优化 prompt 或限制决策空间。
Multi-hop RAG 的评估陷阱:端到端评估无法区分哪跳出错。如果最终答案错误,可能是任何一跳出了问题。必须逐跳评估——每一跳的检索结果和线索提取都单独打分,才能定位薄弱环节。
评估方法的完整框架见 RAG 评估方法论
模式组合实战
六种模式不是互斥的——实际生产中往往是多种模式组合使用。以下是最常见的三种组合方案,以及它们在五个项目中的落地形态。
组合一:Advanced + Graph(企业级标准方案)
这是目前最成熟的企业级 RAG 方案。WeKnora 就是这个组合的典型实现。
管线结构:查询改写(可选) → 多路检索(向量 + BM25 + 图谱) → RRF 融合 → 复合 Rerank → 生成
为什么这样组合:Advanced 的 Rerank 解决”质量把关”问题,Graph 的图谱路解决”间接关联”问题,两者互补且不冲突。多路检索最大化召回率,Rerank 从大量候选中精筛,这是搜索引擎经典的”召回-精排”范式。
在五个项目中的实现:
- WeKnora:完整实现(三路 + RRF + 复合 Rerank),是这一组合的标杆
- Dify:可在 Workflow 中手动搭建,但需要用户自己配置每个节点
- RAGFlow:有向量 + Rerank,缺图谱路
- AnythingLLM:缺 Rerank 和图谱路,不是这个组合
- FastGPT:有向量 + Rerank,缺图谱路
组合二:Modular + Agentic(灵活研究方案)
适合查询多样性高、需要 Agent 自主决策,但每个检索动作内部仍然是模块化管线的场景。
管线结构:Agent ReAct 循环 → 每次检索动作走 Modular 管线(可配置检索器 + 融合 + Rerank) → Agent 判断是否继续
为什么这样组合:Modular 保证了每个检索动作的质量(复用 Advanced 的优化),Agentic 保证了整体编排的灵活性(Agent 决定查什么、查几次)。这好比一个研究团队——每个研究员(Modular 管线)都很专业,项目主管(Agent)决定谁查什么、什么时候汇总。
在五个项目中的实现:
- Dify:Agent 节点内部可以调用 Workflow(即 Modular 管线),天然支持这个组合
- LangGraph:Agent 图中的每个 retrieve 节点可以是一个完整的 Modular 管线
- WeKnora + LangChain:WeKnora 作为 Modular 管线,LangChain Agent 做编排——通过 MCP Server 集成
- FastGPT:Workflow 循环节点可以模拟这个组合,但不是真正的 Agent 编排
组合三:Graph + Multi-hop(深度推理方案)
适合需要深层次链式推理,且领域知识图谱密集的场景——例如法律条文追溯、代码依赖分析、医学诊断链。
管线结构:Multi-hop 推理链 → 每跳同时走向量 + 图谱两路 → 图谱提供确定关系,向量补充上下文 → 级联验证
为什么这样组合:Graph 提供确定性的关系路径(”A 依赖 B”是事实,不是推测),Multi-hop 在此基础上做链式推理(”A 依赖 B → B 依赖 C → C 的安全漏洞影响 A”)。图谱的确定性降低了每跳的误差率,缓解了 Multi-hop 最担心的误差级联问题。
这是目前唯一能让 Multi-hop 在生产环境可靠运行的组合。纯 Multi-hop 每跳依赖 LLM 提取线索(误差率 10-20%),3 跳后端到端准确率只剩 50-70%。但 Graph + Multi-hop 中,图谱提供的关系是预先验证的(准确率 > 95%),3 跳后端到端准确率仍在 85% 以上。
在五个项目中的实现:
- WeKnora + LangGraph:WeKnora 的图谱路提供确定关系,LangGraph 编排 Multi-hop 推理链——这是犀牛鸟竞赛的高价值贡献方向
- Dify:Workflow 循环节点 + 知识检索节点可以近似实现,但缺少内建图谱
- 其他项目:没有同时支持图谱和 Multi-hop 的能力
RAG 模式的前沿趋势
RAG 领域正在快速演进,以下是 2025-2026 年最值得关注的方向:
趋势一:Streaming RAG
传统 RAG 是”检索完再生成”——用户要等整个检索完成后才开始看到回答。Streaming RAG 在检索过程中就逐步生成:第一批 chunk 到了就开始回答,后续 chunk 到了再修正/补充。
这个趋势对 Agentic RAG 尤其重要——Agent 的多轮循环天然适配流式输出,用户不需要等到所有循环结束才看到进展。OpenAI 的 Assistants API 和 Dify 的流式输出都在往这个方向走。
趋势二:Speculative RAG
受 CPU “推测执行”启发——在 LLM 生成答案的同时,并行发起下一轮检索(预测 LLM 可能需要补充的信息)。如果 LLM 确实需要,检索结果已经就绪,零等待;如果不需要,丢弃检索结果,白花一次检索成本但省了等待时间。
这个趋势对 Advanced RAG 的延迟优化很有价值——WeKnora 的三路并行检索已经有一点”推测”的意味(三路全查,即使用户问题只需要一路),但更精细的推测执行可以进一步降低端到端延迟。
趋势三:RAG as Service(检索即服务)
RAG 能力从”应用内置”变成”独立服务”——任何 Agent 都可以通过标准协议(MCP / API)调用 RAG 服务,无需自己实现检索逻辑。WeKnora 的 MCP Server 就是这个方向的早期实践。
这个趋势的核心价值是解耦——Agent 框架专注编排,RAG 平台专注检索质量,各自独立演进。这对犀牛鸟竞赛意味着:WeKnora 不需要自己实现 Agent 编排,只需要把 MCP Server 做好,就能被所有 Agent 框架集成。详见 Agent 与 RAG 平台集成
趋势四:Adaptive Chunking
传统分块是固定长度或固定段落。Adaptive Chunking 根据文档语义结构动态决定分块边界——代码按函数/类分,论文按章节分,对话按轮次分。RAGFlow 的 DeepDoc 解析是这一方向的代表。
更好的分块直接提升所有模式的检索质量——因为分块边界决定了”检索的最小单元”,分块越合理,检索粒度越精准。这是投入产出比最高的优化之一,但也是最容易忽视的——很多人只关注检索算法,忘了分块才是上游的决定性因素。
生产落地注意事项
从实验到生产,六种模式各有需要特别注意的工程问题:
延迟与超时
| 模式 | 典型延迟 | 超时建议 | 降级策略 |
|---|---|---|---|
| Naive | 0.5-1s | 3s | 直接返回”检索超时” |
| Advanced | 1-3s | 5s | 跳过 Rerank,用粗排结果生成 |
| Modular | 1-3s | 5s | 某模块超时时用默认模块替代 |
| Graph | 2-5s | 8s | 跳过图谱路,用向量+BM25 两路 |
| Agentic | 3-15s | 15s | 超过 max_iterations 强制生成 |
| Multi-hop | 5-30s | 30s | 超过 max_hops 用已有证据生成 |
关键原则:任何模式都必须有降级策略。检索超时不能让用户干等,必须返回部分结果或明确提示。WeKnora 的三路并行设计天然有降级空间——任一路超时,其他两路的结果仍然可用。
成本控制
生产环境的成本控制策略:
- 缓存层:对高频查询的检索结果做缓存,相同/相似查询直接返回缓存结果。缓存命中率通常 30-50%,直接砍掉一半检索成本。
- 查询路由:先用轻量分类器判断查询复杂度,简单查询走 Naive 路径,复杂查询走 Advanced/Agentic。避免所有查询都走最贵路径。
- Token 预算:为每个查询设置 token 预算上限,超过预算立即停止检索,用已有证据生成。这和信用卡额度一个道理——防止 Agent 无限循环烧钱。
- 分级服务:对内高优查询走完整管线(包括 Rerank + 图谱),对外低优查询走轻量管线(向量 + 缓存)。不同服务质量不同成本。
可观测性
生产 RAG 系统必须有的监控指标:
- 检索阶段:每路检索的召回数、延迟、错误率;RRF 融合后的排名分布;Rerank 前后的排序变化
- 生成阶段:LLM 调用延迟、token 消耗、生成质量分数(如 Faithfulness)
- 端到端:总延迟、总成本、用户满意度(点赞/点踩)、幻觉率(抽检)
- Agentic 专属:Agent 循环次数分布、每轮决策类型、决策准确率、成本/查询
WeKnora 的 EventManager 事件总线天然支持可观测性——每个事件都有时间戳和载荷,可以追踪请求经过的每一跳。这是固定管线相比 Agent 编排的一个优势:可观测性确定性更强。详见 精读: WeKnora
数据质量是所有模式的地基
无论用哪种模式,如果输入数据质量差,高级模式的效果也不会好——”垃圾进垃圾出”在 RAG 领域尤其成立。数据质量问题的优先级应该高于模式升级:
- 文档解析质量:如果 PDF 解析出来是乱码,再多的检索路也找不到有用信息。RAGFlow 的 DeepDoc 在这个问题上投入最大——先确保”吃进去”的文档是对的,再谈”检索出来”的结果好不好。
- 分块合理性:固定 512 token 分块是最低配方案。语义分块(按段落/章节/函数分)能让所有模式的检索质量提升 10-20%,且不需要任何算法改动。这是投入产出比最高的优化。
- 元数据完整性:文档来源、创建时间、作者、部门等元数据,在 Rerank 和过滤时极有价值。WeKnora 的 Rerank 来源分(0.1 权重)就是利用元数据判断文档可信度。
- 索引时效性:文档更新后向量索引和图谱都需要增量更新。如果索引过期,检索出来的信息可能已经过时——这在知识库自维护场景下尤其重要。WeKnora 的自维护 Wiki 功能正是解决这个问题。
数据质量问题的深入讨论见 技术挑战 第 1-3 条
六种模式的常见误区
每种模式都有初学者容易踩的坑。以下整理了六种模式最常见的误区和正确理解,帮助避免”看起来用了高级模式,实际上效果还不如 Naive”的情况。
误区一:Advanced RAG = 无脑加 HyDE
错误认知:只要加了 HyDE,检索质量就一定会提升。 正确理解:HyDE 只对”短查询”和”抽象查询”有效。当查询本身已经很具体(”WeKnora 的 RRF k 参数值是多少”),HyDE 生成的假答案反而可能引入噪声。更重要的是,当 LLM 对领域不熟悉时(比如新入职的实习生问专业问题),生成的假答案方向可能完全偏了,检索结果比 Naive 更差。
实践建议:HyDE 做成可选开关,根据查询长度和领域置信度动态决定是否启用。短查询(< 10 个词)且高置信度领域开启,长查询或陌生领域关闭。
误区二:Modular RAG = 模块越多越好
错误认知:把 RAG 管线拆成尽可能多的模块,就是更好的 Modular RAG。 正确理解:模块化的唯一目的是”可替换”。如果一个模块永远不会被替换(比如唯一的 embedding 模型),拆成独立模块反而增加了接口复杂度,没有任何收益。过度模块化是微服务领域的经典反模式,在 RAG 领域同样适用。
实践建议:只在满足以下条件之一时才拆模块:(1)有两种以上可替换实现;(2)需要独立 A/B 测试;(3)不同团队分别负责。
误区三:Graph RAG 一定能提升效果
错误认知:加了知识图谱路,检索效果就一定比纯向量好。 正确理解:图谱路的效果取决于图谱质量。如果文档量小(< 1000 篇),实体共现不够,图谱边很少——图谱路退化为空结果,白增加了延迟。如果实体消歧做不好(”苹果”链接到了水果而非公司),图谱路反而引入噪声。如果 2 跳邻居不加限制,噪声爆炸可能让效果比不用图谱还差。
实践建议:加图谱路之前,先评估图谱密度(实体数 / 文档数,关系数 / 实体数)。密度低于阈值(建议 < 2 条关系/实体)时不启用图谱路,走纯向量 + BM25 即可。
误区四:Agentic RAG 一定比固定管线好
错误认知:Agent 自主决定检索策略,当然比固定管线灵活,效果也更好。 正确理解:Agentic RAG 的”灵活性”是双刃剑。Agent 可能做出次优决策——比如检索了一个不相关的知识库,或者在信息已经足够时仍然多检索一轮(浪费成本),更严重的是 Agent 可能”忘了”检索直接用训练知识回答(产生幻觉)。在生产环境中,固定管线的”确定性”往往是比”灵活性”更宝贵的品质。
实践建议:先用固定管线跑通,量化基线指标。只有当固定管线在 > 20% 的查询上明显不足时,才考虑 Agentic。并且 Agentic 一定要设 max_iterations 上限和 token 预算。
误区五:Multi-hop 跳数越多越好
错误认知:推理链越长,挖掘的信息越深入,效果越好。 正确理解:每一跳都引入误差,跳数越多端到端准确率越低。如果单跳准确率 90%,3 跳后只剩 73%,5 跳后只剩 59%。而且每一跳的延迟线性叠加——5 跳可能要 30 秒以上。绝大多数查询 2-3 跳就足够了,4 跳以上除非每跳有严格验证,否则误差级联会让结果不可用。
实践建议:默认 max_hops=2,只在经过验证的特定查询类型上允许 3 跳。每一跳后都做相关性判断,不相关立即停止。
误区六:Rerank 可以替代所有检索优化
错误认知:只要 Rerank 够强,检索阶段的粗排随便做都行。 正确理解:Rerank 只能在 Top-K 结果中重排——如果相关信息根本没进入 Top-K(粗排就漏了),Rerank 再强也无济于事。这是”召回率决定天花板,Rerank 决定天花板下的排序”——召回率不够,Rerank 提升的是排序质量而非覆盖范围。
实践建议:先优化粗排的召回率(多路检索、查询改写),再优化 Rerank 的精排质量。两者缺一不可,且召回率是前置条件。
Naive RAG 到各模式的快速判断清单
当你已经有了一个 Naive RAG,想判断要不要升级时,用这张清单逐项打勾。如果某个模式对应的勾超过一半,就该升级了。
是否需要升级到 Advanced RAG?
- 用户经常抱怨”搜不到”或”搜出来的不相关”
- 查询中包含精确关键词(错误码、版本号、API 名)但经常检索不到
- Top-10 结果中经常混入明显无关的文档
- 用户查询短于 10 个词,语义理解困难
- 文档量超过 1000 篇,单一检索信号不够
- 对答案准确率有明确要求(不是”大概就行”)
勾选 3 个以上:强烈建议升级。Advanced RAG 是性价比最高的升级,几乎没有不升级的理由。
是否需要升级到 Modular RAG?
- 已有 Advanced RAG,但优化模块耦合严重,改一个影响另一个
- 需要 A/B 测试不同 Rerank 模型、不同检索策略
- 多团队协作,各负责不同模块
- 同一套代码需要服务多个场景(内部/对外/不同业务线)
- 模块替换频率高,每月至少换一个组件
勾选 2 个以上:建议升级。Modular 是工程化升级,不提升检索质量但大幅提升可维护性。
是否需要升级到 Graph RAG?
- 用户查询经常涉及实体关系(”A 依赖 B”、”X 的负责人”)
- 文档中实体密度高(每篇文档平均 > 5 个命名实体)
- 已有知识图谱,或有能力构建(能接受每篇文档 1-2 次 LLM 调用的构建成本)
- 传统检索在 > 15% 的查询上遗漏了逻辑相关但语义不相似的文档
- 领域实体消歧可行(”苹果”能区分水果/公司/品牌)
勾选 3 个以上:建议升级。Graph RAG 是差异化最强的模式,但构建成本也最高。
是否需要升级到 Agentic RAG?
- 查询模式 > 5 种,且差异大到无法用条件分支覆盖
- 需要多个数据源协作(内部知识库 + 互联网 + 数据库)
- 固定管线在 > 20% 的查询上”力不从心”(需要动态调整策略)
- 延迟预算允许 3-15 秒(不是实时交互场景)
- 成本预算允许 3-6 倍于固定管线(有 token 预算管理)
- 已有 Agent 框架(LangChain/LangGraph/Dify Agent)
勾选 3 个以上:建议升级。但一定要从”检索即工具”(形态一)开始,不要一上来就做管线可编排(形态三)。
是否需要升级到 Multi-hop RAG?
- 用户查询本质上是链式推理(追溯、影响分析、因果链)
- 单跳检索准确率 > 95%(基础质量够好,级联后仍可用)
- 延迟预算允许 10-30 秒(离线分析/深度研究场景)
- 有完善的每跳验证机制(不会让误差无限制级联)
- 领域知识图谱密集(Graph + Multi-hop 组合可以显著降低误差率)
勾选 3 个以上:建议升级。Multi-hop 是最强但最贵的模式,只在特定领域有价值。
六种模式的延迟与成本全景
把六种模式的延迟和成本放在一起看,能更直观地理解”越高级越贵”的演进逻辑。以下数据基于典型生产配置估算:向量数据库 Milvus/Qdrant、Rerank 模型 bge-reranker-v2-m3、LLM GPT-4o、知识图谱 Neo4j/NetworkX。
延迟分解
| 模式 | 查询向量化 | 检索 | 图谱遍历 | 融合 | Rerank | LLM 推理 | Agent 循环 | 总延迟 |
|---|---|---|---|---|---|---|---|---|
| Naive | 50ms | 100ms | — | — | — | 800ms | — | ~1s |
| Advanced | 50ms | 200ms | — | 50ms | 200ms | 800ms | — | ~1.3s |
| Modular | 50ms | 200ms | — | 50ms | 200ms | 800ms | — | ~1.3s |
| Graph | 50ms | 200ms | 300ms | 100ms | 200ms | 800ms | — | ~1.7s |
| Agentic (2轮) | 50ms | 400ms | — | — | 400ms | 2400ms | 2轮 | ~3.3s |
| Multi-hop (3跳) | 50ms | 300ms | — | — | 300ms | 3500ms | 3跳 | ~4.2s |
注意:以上是”乐观估计”。Agentic 的循环次数不确定,实际可能 3-5 轮。Multi-hop 每跳都可能触发 LLM 推理(提取线索),3 跳的实际延迟可能 10-30 秒。
成本分解(每查询,单位:元)
| 模式 | 向量化 | 检索 | Rerank | LLM 调用 | 图谱维护 | 总成本 |
|---|---|---|---|---|---|---|
| Naive | 0.001 | 0.001 | — | 0.01 | — | ~0.012 |
| Advanced | 0.001 | 0.002 | 0.002 | 0.01 | — | ~0.015 |
| Modular | 0.001 | 0.002 | 0.002 | 0.01 | — | ~0.015 |
| Graph | 0.001 | 0.002 | 0.002 | 0.01 | 0.005 | ~0.02 |
| Agentic (2轮) | 0.001 | 0.004 | 0.004 | 0.03 | — | ~0.04 |
| Multi-hop (3跳) | 0.001 | 0.006 | 0.006 | 0.05 | — | ~0.063 |
结论:从 Naive 到 Multi-hop,成本增长约 5 倍。但考虑到质量提升(准确率可能从 70% 提升到 90%+),在某些场景下 5 倍成本是完全值得的。关键是根据业务价值判断——如果错误答案的成本远高于 5 倍检索成本(医疗诊断、合规审查),Multi-hop 是值得的。
交叉引用
本目录(RAG / 知识库)
| 文档 | 关联点 |
|---|---|
| 行业全景 | 5 项目横评、模式 × 项目矩阵的详细版 |
| 精读: WeKnora | WeKnora 三路检索架构、RRF/Rerank 参数、EventManager |
| 精读: Dify | Dify Workflow/Agent 节点实现 |
| 精读: RAGFlow | RAGFlow DeepDoc 解析 + Rerank |
| 精读: AnythingLLM | AnythingLLM 默认 Naive 模式 |
| 精读: FastGPT | FastGPT Workflow 编排 |
| 竞赛指南: WeKnora 贡献 | 贡献路径与 RAG 模式升级 |
| 技术挑战 | 图谱构建成本、Agentic 多跳成本控制、Rerank 泛化性 |
| Agent 与 RAG 平台集成 | WeKnora MCP/API 集成拓扑 |
| RAG 评估方法论 | 各模式评估指标选择 |
| RAG 平台决策树 | 基于场景选择 RAG 模式 |
| RAG 生产全景 | 各模式生产落地情况 |
AI Memory 目录
| 文档 | 关联点 |
|---|---|
| Memory 与 RAG 边界 | Memory 与 RAG 的职责边界——何时用 Memory、何时用 RAG |
| 记忆设计模式目录 | Temporal Graph 模式与 Graph RAG 的交叉 |
| 精读: cognee | ECL 管线(Extract-Cognify-Load)实现 Graph RAG |
| 精读: graphiti | 时序知识图谱——Graph RAG 的动态版本 |
| AI Memory 全景 | Memory 项目全景,理解 Memory-RAG 生态 |
证据等级
| 来源 | 标签 |
|---|---|
| WeKnora 源码 EventManager / retrieval / mcp-server | [源码] |
| deep-dive-weknora.md RRF/Rerank 参数 | [已有] |
| LangChain docs (create_retriever_tool) | [文档] |
| LangGraph Corrective RAG 模板 | [文档] |
| Dify Workflow 文档 | [文档] |
| Self-RAG / CRAG 论文 | [社区] |
| HyDE 论文 (Gao et al. 2022) | [社区] |
| Microsoft GraphRAG 论文 (Edge et al. 2024) | [社区] |
| IRCoT (Trivedi et al. 2022) | [社区] |
| rag-knowledge-landscape 横评 | [已有] |
| challenges.md 图谱/多跳挑战 | [已有] |
| rag-agent-integration.md 集成拓扑 | [已有] |
| 未实测 | 以上项目均未本地实测,结论以源码/文档/社区为准 |
结语
六种 RAG 模式不是”越高级越好”的等级制,而是针对不同场景的工具箱。选择的关键不是”用最先进的模式”,而是”用刚好够用的模式”——Naive 在简单场景下仍然是最优解,Agentic 在确定场景下反而是过度工程。
记住三个原则:
- 先跑通再优化——从 Naive 开始,按升级路径逐步推进,每一步都有明确的验收标准
- 数据质量优先于模式升级——再高级的模式也无法弥补输入数据的质量问题
- 可控性比灵活性更重要——在生产环境中,可预测的 mediocre 结果优于不可预测的 excellent 结果