从朴素检索到智能体驱动的知识增强,RAG技术栈正在经历一场深刻的范式转移。本文将系统梳理RAG 2.0的核心技术演进,并给出可落地的生产级实现方案。
一、引言
检索增强生成(Retrieval-Augmented Generation, RAG)自2020年由Meta提出以来,已经成为大语言模型(LLM)落地企业场景的核心技术范式。然而,早期的RAG实现——我们称之为Naive RAG——存在诸多局限:检索精度不足、上下文窗口利用率低、缺乏多跳推理能力、难以处理复杂的知识关联。
进入2026年,随着向量数据库的成熟、图数据库与知识图谱的深度整合、以及Agent框架的爆发式增长,RAG技术栈已经演进到一个全新的阶段。业界将这一阶段统称为RAG 2.0,其核心特征包括:
- 混合检索(Hybrid Search):融合稀疏检索与稠密检索,兼顾精确匹配与语义理解
- 图增强检索(GraphRAG):利用知识图谱捕捉实体间的结构化关系,支持多跳推理
- 智能体驱动(Agentic RAG):引入自主决策的Agent,实现动态查询规划与迭代检索
- 端到端评估体系:从检索质量到生成质量的全链路量化评估
本文将从架构演进出发,深入剖析每项核心技术,并提供可直接用于生产环境的代码实现。
二、从 Naive RAG 到 RAG 2.0
2.1 Naive RAG 的典型架构
早期的RAG系统遵循一个简单的三阶段流水线:
用户查询 --> 向量检索(Top-K) --> LLM生成回答
这种架构的问题显而易见:
- 检索质量瓶颈:纯向量检索在精确匹配(如型号、编号)场景下表现不佳
- 单次检索局限:面对需要多步推理的复杂问题,一次检索往往无法获取足够信息
- 上下文污染:Top-K策略容易引入大量无关文档,稀释有效信息
- 知识孤岛:文档被切分为独立的chunk后,跨文档的知识关联被完全割裂
2.2 RAG 2.0 的架构全景
RAG 2.0并非简单的技术堆叠,而是一套完整的知识增强框架。其核心架构如下:
+------------------+
| Agentic Router |
| (查询分析/规划) |
+--------+---------+
|
+------------+------------+
| | |
+-----v----+ +----v-----+ +----v-----+
| 向量检索 | | 关键词 | | 图谱检索 |
| (Dense) | | (Sparse) | | (Graph) |
+-----+----+ +----+-----+ +----+-----+
| | |
+------------+------------+
|
+--------v---------+
| Re-Ranker |
| (交叉编码重排序) |
+--------+---------+
|
+--------v---------+
| Context Builder |
| (上下文压缩/组装)|
+--------+---------+
|
+--------v---------+
| LLM Generator |
| (带引用的生成) |
+------------------+
与Naive RAG相比,RAG 2.0的关键变化在于:引入了智能路由层来动态选择检索策略,采用多路召回融合替代单一向量检索,增加了重排序层来优化检索结果质量,并通过上下文压缩技术最大化有效信息密度。
三、核心技术演进
3.1 混合检索:稀疏与稠密的最佳融合
混合检索的核心思想是:稠密向量擅长语义匹配,稀疏向量擅长精确匹配,两者的结合可以覆盖更广泛的检索场景。
在实际实现中,我们通常采用倒数排名融合(Reciprocal Rank Fusion, RRF)来合并多路检索结果:
from dataclasses import dataclass
from typing import List, Dict
import numpy as np
@dataclass
class SearchResult:
doc_id: str
content: str
score: float
class HybridRetriever:
"""混合检索器:融合稠密检索、稀疏检索与重排序"""
def __init__(self, dense_index, sparse_index, reranker, k: int = 60):
self.dense_index = dense_index # 向量索引(如Milvus/Qdrant)
self.sparse_index = sparse_index # 稀疏索引(如Elasticsearch BM25)
self.reranker = reranker # 交叉编码器重排模型
self.k = k
def reciprocal_rank_fusion(
self,
results_list: List[List[SearchResult]],
k_rrf: int = 60
) -> List[SearchResult]:
"""RRF融合多路检索结果"""
doc_scores: Dict[str, float] = {}
doc_map: Dict[str, SearchResult] = {}
for results in results_list:
for rank, result in enumerate(results):
doc_id = result.doc_id
doc_scores[doc_id] = doc_scores.get(doc_id, 0.0)
doc_scores[doc_id] += 1.0 / (k_rrf + rank + 1)
doc_map[doc_id] = result
sorted_docs = sorted(doc_scores.items(), key=lambda x: x[1], reverse=True)
return [
SearchResult(doc_id=did, content=doc_map[did].content, score=score)
for did, score in sorted_docs
]
def retrieve(self, query: str, top_k: int = 10) -> List[SearchResult]:
# 第一阶段:多路召回
dense_results = self.dense_index.search(query, top_n=self.k)
sparse_results = self.sparse_index.search(query, top_n=self.k)
# 第二阶段:RRF融合
fused = self.reciprocal_rank_fusion([dense_results, sparse_results])
# 第三阶段:交叉编码器重排序
candidates = fused[:top_k * 3] # 取融合后前3倍候选
reranked = self.reranker.rerank(query, candidates)
return reranked[:top_k]
在生产环境中,稀疏检索推荐使用Elasticsearch 8.x的原生BM25,稠密检索推荐使用Qdrant或Milvus,重排序模型推荐使用bge-reranker-v2.5或Cohere Rerank。融合权重需要根据具体业务场景通过评估数据集进行调优。
3.2 GraphRAG:知识图谱驱动的结构化检索
GraphRAG是2024至2025年间RAG领域最重要的技术突破之一。其核心思路是:在传统的向量检索基础上,引入知识图谱来捕捉文档中实体之间的结构化关系,从而支持多跳推理和全局摘要。
GraphRAG的典型构建流程包含三个阶段:
阶段一:图谱构建——从文档中抽取实体和关系,构建知识图谱 阶段二:社区检测——利用图算法(如Leiden算法)发现知识社区,生成社区摘要 阶段三:混合查询——将图谱检索与向量检索结合,支持局部查询和全局查询
from typing import List, Tuple, Optional
import networkx as nx
class GraphRAGPipeline:
"""GraphRAG核心流水线"""
def __init__(self, llm_client, embedding_model, graph_store):
self.llm = llm_client
self.embedder = embedding_model
self.graph = graph_store # 如Neo4j或NetworkX
def extract_entities_and_relations(
self, text_chunk: str
) -> List[Tuple[str, str, str]]:
"""利用LLM从文本中抽取三元组 (head, relation, tail)"""
prompt = f"""请从以下文本中抽取所有实体和关系,以三元组形式返回。
格式要求:每行一个三元组,格式为 (实体1, 关系, 实体2)
文本:
{text_chunk}
三元组列表:"""
response = self.llm.generate(prompt)
return self._parse_triples(response)
def build_knowledge_graph(self, documents: List[str]) -> nx.Graph:
"""从文档集合构建知识图谱"""
G = nx.Graph()
for doc in documents:
chunks = self._split_document(doc)
for chunk in chunks:
triples = self.extract_entities_and_relations(chunk)
for head, relation, tail in triples:
G.add_node(head, type="entity")
G.add_node(tail, type="entity")
G.add_edge(head, tail, relation=relation, source=chunk)
return G
def community_detection(self, G: nx.Graph) -> dict:
"""使用Leiden算法进行社区检测并生成社区摘要"""
from cdlib import algorithms
communities = algorithms.leiden(G)
community_summaries = {}
for idx, community in enumerate(communities.communities):
subgraph = G.subgraph(community)
edges_info = [
f"{u} --[{d['relation']}]--> {v}"
for u, v, d in subgraph.edges(data=True)
]
summary_prompt = f"请总结以下知识关系网络的核心内容:\n" + "\n".join(edges_info)
community_summaries[idx] = self.llm.generate(summary_prompt)
return community_summaries
def query(self, question: str, mode: str = "local") -> str:
"""
查询接口
- local模式:从相关实体出发,沿图谱进行局部子图检索
- global模式:基于社区摘要进行全局检索
"""
if mode == "local":
return self._local_search(question)
else:
return self._global_search(question)
GraphRAG的核心价值在于处理那些需要跨文档关联推理的场景。例如,当用户提问"公司A的CEO曾在哪些公司B的合作伙伴中任职"时,传统向量检索很难一步到位地获取答案,而图谱检索可以沿着实体关系路径高效地完成多跳推理。
需要注意的是,GraphRAG的图谱构建成本较高,通常需要消耗大量的LLM调用。在实际项目中,建议对图谱构建实施增量更新策略,避免每次全量重建。
3.3 Agentic RAG:从被动检索到自主推理
Agentic RAG是RAG 2.0中最具革命性的变化。传统RAG的检索流程是预定义的、固定的,而Agentic RAG赋予系统自主决策的能力——Agent可以根据问题的复杂度动态规划检索策略,在必要时进行多轮迭代检索,并在检索结果不充分时主动调整方向。
from enum import Enum
from typing import List, Any
class Action(Enum):
VECTOR_SEARCH = "vector_search"
GRAPH_SEARCH = "graph_search"
WEB_SEARCH = "web_search"
SUMMARIZE = "summarize"
ANSWER = "answer"
class RAGAgent:
"""Agentic RAG:具备自主检索与推理能力的RAG智能体"""
MAX_ITERATIONS = 5
def __init__(self, llm, retriever, graph_rag, web_searcher):
self.llm = llm
self.retriever = retriever
self.graph_rag = graph_rag
self.web_searcher = web_searcher
self.scratchpad: List[str] = [] # 工作记忆
def plan_next_action(self, query: str, context: str) -> Action:
"""基于当前状态规划下一步动作"""
prompt = f"""你是一个检索规划智能体。根据用户问题和已有上下文,决定下一步动作。
用户问题:{query}
已收集的上下文:
{context if context else "(暂无)"}
可选动作:
- vector_search:执行向量语义检索,适合获取与问题语义相关的文档片段
- graph_search:执行知识图谱检索,适合需要实体关系推理的问题
- web_search:执行网络搜索,适合需要最新信息的问题
- summarize:对已有上下文进行摘要整理
- answer:上下文已充分,可以直接回答
请只返回动作名称,不要包含其他内容。"""
action_str = self.llm.generate(prompt).strip().lower()
return Action(action_str)
def execute_action(self, action: Action, query: str) -> str:
"""执行规划的动作"""
if action == Action.VECTOR_SEARCH:
results = self.retriever.retrieve(query, top_k=5)
return "\n".join([r.content for r in results])
elif action == Action.GRAPH_SEARCH:
return self.graph_rag.query(query, mode="local")
elif action == Action.WEB_SEARCH:
return self.web_searcher.search(query)
elif action == Action.SUMMARIZE:
return self._summarize_scratchpad()
return ""
def run(self, query: str) -> str:
"""主循环:迭代式检索-推理"""
context = ""
for step in range(self.MAX_ITERATIONS):
action = self.plan_next_action(query, context)
if action == Action.ANSWER:
break
result = self.execute_action(action, query)
self.scratchpad.append(f"[Step {step+1}] {action.value}: {result[:500]}")
context = "\n\n".join(self.scratchpad)
# 最终生成回答
answer_prompt = f"""基于以下检索到的上下文信息,回答用户问题。
请在回答中标注信息来源,如果上下文不足以回答,请明确说明。
上下文:
{context}
问题:{query}
回答:"""
return self.llm.generate(answer_prompt)
Agentic RAG的关键设计要点包括:
- 查询分解:Agent应能将复杂问题拆解为多个子问题,分别检索后综合回答
- 检索充分性判断:Agent需要评估已检索信息是否足以回答问题,不足时继续检索
- 迭代上限控制:必须设置最大迭代次数,防止Agent陷入无限循环
- 工作记忆管理:随着迭代进行,需要对中间结果进行摘要压缩,避免上下文爆炸
四、实战:构建生产级RAG系统
4.1 文档处理流水线
生产级RAG系统的第一个挑战是文档处理。粗暴的固定长度切分会破坏语义完整性,推荐采用语义感知的分块策略:
from typing import List
import numpy as np
class SemanticChunker:
"""基于语义相似度的自适应文档分块"""
def __init__(self, embedding_model, similarity_threshold: float = 0.75):
self.embedder = embedding_model
self.threshold = similarity_threshold
def chunk(self, text: str, max_chunk_size: int = 512) -> List[str]:
# 第一步:按句子切分
sentences = self._split_sentences(text)
if len(sentences) <= 1:
return sentences
# 第二步:计算相邻句子的语义相似度
embeddings = self.embedder.encode(sentences)
similarities = [
np.dot(embeddings[i], embeddings[i + 1])
/ (np.linalg.norm(embeddings[i]) * np.linalg.norm(embeddings[i + 1]))
for i in range(len(embeddings) - 1)
]
# 第三步:在相似度低谷处切分
chunks = []
current_chunk = [sentences[0]]
for i, sim in enumerate(similarities):
if sim < self.threshold and self._token_count(current_chunk) >= max_chunk_size // 2:
chunks.append("".join(current_chunk))
current_chunk = [sentences[i + 1]]
else:
current_chunk.append(sentences[i + 1])
if current_chunk:
chunks.append("".join(current_chunk))
return chunks
def _split_sentences(self, text: str) -> List[str]:
"""中文分句"""
import re
return [s.strip() for s in re.split(r'(?<=[。!?;])', text) if s.strip()]
def _token_count(self, sentences: List[str]) -> int:
return sum(len(s) for s in sentences)
4.2 生产部署架构要点
一个成熟的生产级RAG系统还需要关注以下工程细节:
- 索引更新策略:采用增量索引而非全量重建,通过变更数据捕获(CDC)机制监听数据源变化
- 缓存层设计:对高频查询的检索结果和生成结果分别做缓存,语义相似查询可共享缓存
- 可观测性:对检索延迟、召回文档数量、LLM Token消耗、端到端响应时间等关键指标进行全链路埋点
- 降级策略:当向量数据库不可用时,自动降级到纯稀疏检索;当LLM服务超时时,返回检索到的原文片段
五、评估与优化
RAG系统的评估是一个长期被忽视但至关重要的环节。RAG 2.0时代,评估体系已经从简单的人工抽检演进为结构化的自动评估框架。
5.1 评估维度
一个完整的RAG评估框架应覆盖以下四个核心维度:
| 维度 | 度量指标 | 评估方法 |
|---|---|---|
| 检索相关性 | Precision@K, nDCG, MRR | 基于标注数据集计算 |
| 上下文充分性 | Context Recall, Coverage | LLM-as-Judge评估 |
| 答案忠实度 | Faithfulness, Hallucination Rate | 答案与上下文的蕴含关系检测 |
| 答案有用性 | Answer Relevancy, Completeness | LLM-as-Judge + 人工抽检 |
5.2 自动化评估实现
以下是一个基于LLM-as-Judge模式的评估框架实现:
from dataclasses import dataclass
from typing import List, Optional
@dataclass
class EvalSample:
question: str
ground_truth: str
retrieved_contexts: List[str]
generated_answer: str
@dataclass
class EvalResult:
faithfulness: float # 忠实度:答案是否基于检索到的上下文
relevancy: float # 相关性:答案是否切题
context_precision: float # 上下文精度:检索结果是否相关
overall: float # 综合得分
class RAGEvaluator:
"""RAG系统全链路评估器"""
def __init__(self, judge_llm):
self.judge = judge_llm
def evaluate_faithfulness(self, sample: EvalSample) -> float:
"""评估答案对检索上下文的忠实度"""
context = "\n---\n".join(sample.retrieved_contexts)
prompt = f"""请评估以下回答是否忠实于给定的上下文信息。
忠实意味着回答中的每个事实性陈述都能在上下文中找到依据。
上下文:
{context}
回答:
{sample.generated_answer}
请给出0到1之间的忠实度评分(1表示完全忠实),并简要说明理由。
格式:分数|理由"""
result = self.judge.generate(prompt)
score = float(result.split("|")[0].strip())
return min(max(score, 0.0), 1.0)
def evaluate_relevancy(self, sample: EvalSample) -> float:
"""评估答案与问题的相关性"""
prompt = f"""请评估以下回答与问题的相关性。
问题:{sample.question}
回答:{sample.generated_answer}
请给出0到1之间的相关性评分(1表示高度相关),并简要说明理由。
格式:分数|理由"""
result = self.judge.generate(prompt)
score = float(result.split("|")[0].strip())
return min(max(score, 0.0), 1.0)
def evaluate(self, samples: List[EvalSample]) -> EvalResult:
"""批量评估"""
faithfulness_scores = []
relevancy_scores = []
for sample in samples:
f_score = self.evaluate_faithfulness(sample)
r_score = self.evaluate_relevancy(sample)
faithfulness_scores.append(f_score)
relevancy_scores.append(r_score)
avg_faith = sum(faithfulness_scores) / len(faithfulness_scores)
avg_rel = sum(relevancy_scores) / len(relevancy_scores)
return EvalResult(
faithfulness=round(avg_faith, 3),
relevancy=round(avg_rel, 3),
context_precision=0.0, # 需要标注数据,此处省略
overall=round((avg_faith + avg_rel) / 2, 3)
)
5.3 持续优化策略
基于评估结果,RAG系统的优化可以从以下几个方向入手:
检索层优化:如果Context Precision偏低,优先调整分块策略(chunk size、overlap比例)和Embedding模型选择。中文场景推荐使用bge-m3或gte-Qwen2等针对中文优化的模型。
重排序层优化:如果召回文档中存在大量无关内容,增加或强化重排序模型。交叉编码器虽然计算开销大,但对排序质量的提升往往是显著的。
生成层优化:如果Faithfulness偏低,需要在Prompt中强化"仅基于上下文回答"的指令约束,必要时引入引用标注机制,要求模型在回答中标注信息来源的具体段落。
数据层优化:定期分析"检索失败"的case,将其转化为评估数据集的一部分,形成"评估-优化-再评估"的闭环。
六、总结
RAG 2.0代表了检索增强生成技术从"能用"到"好用"的关键跃迁。回顾本文讨论的核心要点:
- 混合检索解决了单一检索模式的覆盖盲区,通过RRF融合和重排序实现了检索质量的显著提升
- GraphRAG通过引入知识图谱,为RAG系统增加了结构化推理能力,尤其在多跳推理场景下表现突出
- Agentic RAG将RAG从固定流水线升级为自主决策的智能系统,能够根据问题复杂度动态调整检索策略
- 系统化的评估框架是RAG系统持续改进的基石,LLM-as-Judge模式大幅降低了评估的人力成本
从工程实践的角度来看,构建生产级RAG系统并非一蹴而就。建议团队采用渐进式演进策略:先搭建基于混合检索的基线系统,确保基本检索质量;再根据业务场景需要,逐步引入GraphRAG处理复杂关联查询,引入Agentic RAG处理多步推理任务。在整个过程中,保持评估体系的同步建设,用数据驱动每一次架构决策。
RAG技术仍在快速演进中。可以预见,随着多模态检索、长上下文模型、以及更强大的Agent框架的发展,RAG 2.0还将继续迭代。但其核心理念——让大语言模型基于可靠的外部知识生成准确回答——将始终不变。
本文所有代码示例均为架构层面的示意实现,生产环境中需要根据具体技术栈进行适配。推荐的开源工具链包括:LangChain / LlamaIndex(编排框架)、Qdrant / Milvus(向量数据库)、Neo4j(图数据库)、RAGAS / DeepEval(评估框架)。