11e - 高级 RAG 技术
本文是《AI Agent 实战手册》第 11 章第 5 节。 上一节:11d-RAG系统构建教程 | 下一节:11f-RAG评估与优化
概述
基础 RAG 系统(Naive RAG)虽然能完成”检索 + 生成”的基本流程,但在面对复杂查询、多模态数据、语义与关键词不匹配等场景时往往力不从心。本节系统介绍五大高级 RAG 技术——混合搜索(Hybrid Search)、重排序(Reranking)、查询转换与 HyDE、多模态 RAG、以及 Agentic RAG,帮助你将 RAG 系统从”能用”提升到”好用”。每种技术均包含原理讲解、工具推荐、代码示例和实战提示词模板。
1. 混合搜索(Hybrid Search)
核心原理
混合搜索将稀疏检索(BM25 关键词匹配)与稠密检索(向量语义搜索)结合,通过 Reciprocal Rank Fusion(RRF)或加权融合算法合并两路结果。这样既能捕获精确的关键词匹配(如产品型号、错误代码),又能理解语义相似性(如同义词、上下文含义)。
为什么需要混合搜索?
- 纯向量搜索可能遗漏精确关键词匹配(如
ERROR_CODE_4032) - 纯关键词搜索无法理解语义(如”如何修复内存泄漏”匹配不到”memory leak resolution”)
- 混合搜索在多项基准测试中比单一检索方式提升 10-30% 的召回率
工具推荐
| 工具 | 用途 | 价格 | 适用场景 |
|---|---|---|---|
| Qdrant | 原生支持稀疏+稠密混合搜索 | 免费(自托管);云版 ~$10/月起 | 生产级混合搜索,过滤能力强 |
| Weaviate | 内置 BM25 + 向量混合搜索 | 免费(自托管);云版 $25/月起 | 开箱即用的混合搜索 |
| Pinecone | 支持稀疏-稠密混合索引 | 免费层 2GB;标准版 $70/月起 | 全托管,零运维 |
| pgvector + pg_textsearch | PostgreSQL 原生混合搜索 | 免费(随 PostgreSQL) | 已有 PG 基础设施 |
| Elasticsearch | 经典 BM25 + kNN 向量搜索 | 免费(自托管);云版 $95/月起 | 企业级全文搜索 + 向量 |
| Meilisearch | 轻量级混合搜索引擎 | 免费(开源);云版 $30/月起 | 快速原型,开发者友好 |
操作步骤
步骤 1:理解 RRF 融合算法
Reciprocal Rank Fusion(RRF)是最常用的混合搜索融合算法,公式为:
RRF_score(d) = Σ 1 / (k + rank_i(d))其中 k 通常取 60,rank_i(d) 是文档 d 在第 i 路检索中的排名。RRF 的优势在于不需要对不同检索方式的分数进行归一化。
步骤 2:使用 Qdrant 实现混合搜索(Python)
from qdrant_client import QdrantClient, models
from fastembed import TextEmbedding, SparseTextEmbedding
# 初始化客户端和模型
client = QdrantClient(url="http://localhost:6333")
dense_model = TextEmbedding("BAAI/bge-small-en-v1.5")
sparse_model = SparseTextEmbedding("Qdrant/bm25")
# 创建支持混合搜索的集合
client.create_collection(
collection_name="hybrid_docs",
vectors_config={
"dense": models.VectorParams(
size=384, distance=models.Distance.COSINE
)
},
sparse_vectors_config={
"sparse": models.SparseVectorParams(
modifier=models.Modifier.IDF # 启用 BM25 IDF 加权
)
},
)
# 索引文档(同时生成稠密和稀疏向量)
documents = ["RAG 系统的核心是检索增强生成...", "向量数据库存储嵌入向量..."]
dense_vectors = list(dense_model.embed(documents))
sparse_vectors = list(sparse_model.embed(documents))
for i, doc in enumerate(documents):
client.upsert(
collection_name="hybrid_docs",
points=[models.PointStruct(
id=i,
vector={
"dense": dense_vectors[i].tolist(),
"sparse": models.SparseVector(
indices=sparse_vectors[i].indices.tolist(),
values=sparse_vectors[i].values.tolist(),
)
},
payload={"text": doc}
)]
)
# 混合搜索查询(RRF 融合)
query = "什么是 RAG?"
query_dense = list(dense_model.embed([query]))[0]
query_sparse = list(sparse_model.embed([query]))[0]
results = client.query_points(
collection_name="hybrid_docs",
prefetch=[
models.Prefetch(
query=query_dense.tolist(), using="dense", limit=20
),
models.Prefetch(
query=models.SparseVector(
indices=query_sparse.indices.tolist(),
values=query_sparse.values.tolist(),
),
using="sparse", limit=20
),
],
query=models.FusionQuery(fusion=models.Fusion.RRF), # RRF 融合
limit=10,
)步骤 3:使用 Weaviate 实现混合搜索(TypeScript)
import weaviate from 'weaviate-client';
const client = await weaviate.connectToLocal();
// 创建集合(自动支持混合搜索)
const collection = await client.collections.create({
name: 'HybridDocs',
vectorizers: [
weaviate.configure.vectorizer.text2VecOpenAI({
name: 'default',
model: 'text-embedding-3-small',
}),
],
});
// 混合搜索:alpha 控制语义 vs 关键词权重
// alpha=0.75 表示 75% 语义 + 25% 关键词
const results = await collection.query.hybrid('RAG 系统架构', {
alpha: 0.75, // 0=纯关键词, 1=纯语义
limit: 10,
fusionType: 'RelativeScore', // 或 'Ranked'(RRF)
returnProperties: ['text', 'title'],
});
for (const item of results.objects) {
console.log(item.properties.title, item.metadata?.score);
}提示词模板
你是一个 RAG 系统架构师。请根据以下需求设计混合搜索策略:
**数据特征:**
- 文档类型:[技术文档/法律合同/客服对话/产品目录]
- 是否包含专有名词或编码:[是/否]
- 查询语言:[中文/英文/多语言]
**请输出:**
1. 推荐的稀疏检索方案(BM25 变体选择)
2. 推荐的稠密检索方案(嵌入模型选择)
3. 融合策略(RRF/加权/学习排序)及参数建议
4. alpha 权重建议及调优方向
5. 预期的召回率提升范围2. 重排序(Reranking)
核心原理
重排序是在初始检索之后增加的”精排”阶段。初始检索(向量搜索或混合搜索)通常使用双编码器(Bi-Encoder),速度快但精度有限;重排序使用交叉编码器(Cross-Encoder),将查询和文档拼接后联合编码,能捕获更细粒度的语义交互,显著提升排序质量。
检索流程变为:
查询 → 初始检索(Top-K=50~100)→ 重排序(Top-N=5~10)→ LLM 生成重排序通常能将检索精度提升 10-30%,是投入产出比最高的 RAG 优化手段之一。
工具推荐
| 工具 | 用途 | 价格 | 适用场景 |
|---|---|---|---|
| Cohere Rerank v4 | 商业重排序 API(最新版) | $2/千次查询 | 生产级,支持 100+ 语言,半结构化数据 |
| Cohere Rerank v3.5 | 商业重排序 API | $2/千次查询 | 复杂文档和推理型查询 |
| ZeroEntropy zerank-1 | 超低延迟重排序 | 联系销售 | 对延迟敏感的实时场景 |
| Jina Reranker v2 | 开源/API 重排序 | 免费(开源);API $0.02/千次 | 多语言,代码搜索 |
| BAAI/bge-reranker-v2-m3 | 开源交叉编码器 | 免费(MIT 开源) | 自托管,多语言 |
| Voyage Reranker | 重排序 API | $0.05/百万 tokens | 代码和技术文档 |
| ColBERT v2 | 延迟交互模型 | 免费(开源) | 高效重排序,支持预计算 |
操作步骤
步骤 1:使用 Cohere Rerank API(Python)
import cohere
co = cohere.Client("YOUR_COHERE_API_KEY")
# 假设已从向量搜索获取初始结果
query = "如何优化 RAG 系统的检索精度?"
initial_results = [
"RAG 系统通过检索外部知识来增强 LLM 的生成能力...",
"向量数据库的索引策略直接影响检索速度...",
"重排序模型可以将检索精度提升 10-30%...",
"分块策略的选择对 RAG 质量至关重要...",
"嵌入模型的微调可以显著提升领域内检索效果...",
]
# 重排序
rerank_response = co.rerank(
model="rerank-v3.5",
query=query,
documents=initial_results,
top_n=3, # 只保留 Top-3
return_documents=True,
)
for result in rerank_response.results:
print(f"排名: {result.index}, 相关性: {result.relevance_score:.4f}")
print(f"文档: {result.document.text[:100]}...")
print()步骤 2:使用开源 Cross-Encoder 自托管(Python)
from sentence_transformers import CrossEncoder
# 加载开源重排序模型
reranker = CrossEncoder("BAAI/bge-reranker-v2-m3", max_length=512)
query = "RAG 系统如何处理多语言文档?"
documents = [
"多语言 RAG 需要选择支持多语言的嵌入模型...",
"ChromaDB 是一个轻量级向量数据库...",
"跨语言检索可以使用 multilingual-e5-large 模型...",
]
# 计算查询-文档对的相关性分数
pairs = [[query, doc] for doc in documents]
scores = reranker.predict(pairs)
# 按分数排序
ranked = sorted(zip(documents, scores), key=lambda x: x[1], reverse=True)
for doc, score in ranked:
print(f"[{score:.4f}] {doc[:80]}...")步骤 3:在 LangChain 中集成重排序(Python)
from langchain_community.document_compressors import CohereRerank
from langchain.retrievers import ContextualCompressionRetriever
from langchain_community.vectorstores import Qdrant
from langchain_openai import OpenAIEmbeddings
# 基础检索器
vectorstore = Qdrant.from_existing_collection(
embedding=OpenAIEmbeddings(model="text-embedding-3-small"),
collection_name="my_docs",
url="http://localhost:6333",
)
base_retriever = vectorstore.as_retriever(search_kwargs={"k": 20})
# 添加 Cohere 重排序
compressor = CohereRerank(
model="rerank-v3.5",
top_n=5,
cohere_api_key="YOUR_KEY",
)
# 组合:先检索 20 条,再重排序取 Top-5
compression_retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=base_retriever,
)
results = compression_retriever.invoke("如何设计 Agent 记忆系统?")提示词模板
你是一个搜索质量优化专家。请帮我设计重排序策略:
**当前系统状况:**
- 初始检索方式:[向量搜索/混合搜索/BM25]
- 初始检索 Top-K:[数量]
- 平均查询延迟要求:[毫秒]
- 部署环境:[云端 API/自托管 GPU/CPU-only]
**请推荐:**
1. 最适合的重排序模型及理由
2. Top-K → Top-N 的参数建议
3. 预期的精度提升和延迟增加
4. 是否需要级联重排序(粗排→精排)
5. 成本估算(按月查询量 [数量] 计算)3. 查询转换与 HyDE
核心原理
查询转换(Query Transformation)是在检索前对用户查询进行改写或扩展,以提升检索效果。核心思想是:用户的原始查询往往简短、模糊,与知识库中的文档在表达方式上存在”语义鸿沟”。
主要技术:
| 技术 | 原理 | 适用场景 |
|---|---|---|
| HyDE(Hypothetical Document Embeddings) | 先让 LLM 生成一个”假设性回答文档”,再用该文档的嵌入去检索 | 查询与文档风格差异大 |
| 查询改写(Query Rewriting) | 用 LLM 将模糊查询改写为更精确的检索查询 | 口语化查询、多义词 |
| 查询分解(Query Decomposition) | 将复杂查询拆分为多个子查询,分别检索后合并 | 多方面的复合问题 |
| Step-Back Prompting | 先生成更抽象的高层问题,检索后再回答具体问题 | 需要背景知识的问题 |
| HyPE(Hypothetical Prompt Embeddings) | 预计算每个文档块的假设性问题,将检索变为问题-问题匹配 | 离线预处理,运行时零延迟 |
工具推荐
| 工具 | 用途 | 价格 | 适用场景 |
|---|---|---|---|
| LangChain | 内置多种查询转换链 | 免费(开源) | 快速集成 HyDE、多查询、分解 |
| LlamaIndex | 查询转换模块 | 免费(开源) | HyDE、Sub-Question 查询引擎 |
| OpenAI GPT-4o-mini | 查询改写/HyDE 生成 | $0.15/百万输入 tokens | 高质量查询转换,成本低 |
| Claude 3.5 Haiku | 查询改写/HyDE 生成 | $0.25/百万输入 tokens | 快速推理,适合实时转换 |
| DSPy | 自动优化查询转换 pipeline | 免费(开源) | 自动调优 prompt 和参数 |
操作步骤
步骤 1:实现 HyDE(Python)
from openai import OpenAI
import numpy as np
client = OpenAI()
def hyde_search(query: str, vectorstore, k: int = 5):
"""HyDE: 先生成假设文档,再用假设文档的嵌入检索"""
# 第一步:让 LLM 生成假设性回答
hyde_response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{
"role": "system",
"content": "请直接回答以下问题,写一段详细的技术文档段落。"
"不需要说明这是假设性的,直接写内容。"
}, {
"role": "user",
"content": query
}],
temperature=0.7,
max_tokens=300,
)
hypothetical_doc = hyde_response.choices[0].message.content
# 第二步:用假设文档的嵌入去检索真实文档
# 假设文档的嵌入与真实文档在向量空间中更接近
results = vectorstore.similarity_search(hypothetical_doc, k=k)
return results, hypothetical_doc
# 使用示例
query = "微服务架构下如何实现分布式事务?"
results, hyde_doc = hyde_search(query, my_vectorstore)
print(f"HyDE 生成的假设文档:\n{hyde_doc[:200]}...")
print(f"\n检索到 {len(results)} 个相关文档")步骤 2:实现查询分解(Python)
from openai import OpenAI
client = OpenAI()
def decompose_query(query: str) -> list[str]:
"""将复杂查询分解为多个子查询"""
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{
"role": "system",
"content": (
"你是一个查询分解专家。将用户的复杂问题分解为 2-4 个独立的子问题,"
"每个子问题可以独立检索。输出 JSON 数组格式。"
)
}, {
"role": "user",
"content": query
}],
response_format={"type": "json_object"},
)
import json
result = json.loads(response.choices[0].message.content)
return result.get("sub_queries", [])
def multi_query_search(query: str, vectorstore, k_per_query: int = 3):
"""分解查询 → 分别检索 → 去重合并"""
sub_queries = decompose_query(query)
print(f"分解为 {len(sub_queries)} 个子查询: {sub_queries}")
all_docs = []
seen_ids = set()
for sub_q in sub_queries:
docs = vectorstore.similarity_search(sub_q, k=k_per_query)
for doc in docs:
doc_id = hash(doc.page_content)
if doc_id not in seen_ids:
seen_ids.add(doc_id)
all_docs.append(doc)
return all_docs
# 使用示例
query = "对比 RAG 和微调的优缺点,以及各自适合什么场景?"
results = multi_query_search(query, my_vectorstore)步骤 3:实现 HyPE 预计算(Python)
from openai import OpenAI
client = OpenAI()
def generate_hypothetical_questions(chunk: str, n: int = 3) -> list[str]:
"""为文档块预生成假设性问题(离线阶段)"""
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{
"role": "system",
"content": (
f"阅读以下文档段落,生成 {n} 个用户可能会问的问题。"
"这些问题应该能通过该段落回答。输出 JSON 数组。"
)
}, {
"role": "user",
"content": chunk
}],
response_format={"type": "json_object"},
)
import json
result = json.loads(response.choices[0].message.content)
return result.get("questions", [])
# 离线预处理:为每个文档块生成假设问题并索引
for chunk in document_chunks:
questions = generate_hypothetical_questions(chunk.text)
for q in questions:
# 将问题的嵌入存入向量库,关联到原始文档块
vectorstore.add_texts(
texts=[q],
metadatas=[{"source_chunk_id": chunk.id, "type": "hype_question"}]
)
# 运行时:用户查询直接与预计算的问题嵌入匹配(零额外延迟)
results = vectorstore.similarity_search(user_query, k=5)提示词模板
你是一个 RAG 查询优化专家。请分析以下查询并推荐最佳的查询转换策略:
**原始查询:** [用户查询]
**知识库特征:** [技术文档/FAQ/学术论文/产品手册]
**当前检索效果:** [好/一般/差,简述问题]
**请输出:**
1. 查询类型判断(简单事实/复合问题/模糊意图/对比分析)
2. 推荐的转换策略(HyDE/查询改写/查询分解/Step-Back/不需要转换)
3. 转换后的查询示例
4. 预期的检索效果改善
5. 额外的延迟和成本估算4. 多模态 RAG(Multimodal RAG)
核心原理
多模态 RAG 将检索和生成扩展到文本之外的数据类型——图像、表格、图表、音频、视频等。在企业场景中,大量知识以非纯文本形式存在(如架构图、数据表格、产品照片、会议录音),传统纯文本 RAG 无法有效利用这些信息。
三种主要实现路径:
- 多模态嵌入统一索引:使用 CLIP/SigLIP 等模型将文本和图像映射到同一向量空间
- 视觉 LLM 文本化:用 GPT-4o/Claude 3.5 将图像转为文本描述后索引
- 原生多模态生成:检索时保留原始模态,由多模态 LLM 直接处理
工具推荐
| 工具 | 用途 | 价格 | 适用场景 |
|---|---|---|---|
| LlamaIndex 多模态模块 | 多模态 RAG 框架 | 免费(开源) | 图文混合 RAG pipeline |
| LlamaParse | 复杂文档解析(PDF/PPT) | 免费层 1000 页/天;$3/千页 | 含图表的 PDF 解析 |
| Unstructured | 文档解析和分区 | 免费(开源);API $0.01/页 | 多格式文档预处理 |
| OpenAI CLIP | 图文跨模态嵌入 | 免费(开源) | 图文统一向量空间 |
| GPT-4o | 多模态理解和生成 | $2.50/百万输入 tokens | 图像理解、表格解析 |
| Claude 3.5 Sonnet | 多模态理解 | $3/百万输入 tokens | PDF/图像分析,长文档 |
| Milvus | 支持多向量类型存储 | 免费(开源);Zilliz Cloud $65/月起 | 多模态向量统一存储 |
| ColPali/ColQwen | 视觉文档检索模型 | 免费(开源) | 直接对文档页面图像检索 |
操作步骤
步骤 1:使用 LlamaParse 解析含图表的 PDF
from llama_parse import LlamaParse
from llama_index.core import VectorStoreIndex
# 解析 PDF(自动提取文本、表格、图像)
parser = LlamaParse(
api_key="YOUR_LLAMA_CLOUD_KEY",
result_type="markdown", # 输出 Markdown 格式
use_vendor_multimodal_model=True, # 使用多模态模型解析图表
vendor_multimodal_model="openai-gpt-4o",
language="ch_sim", # 中文支持
)
documents = parser.load_data("./technical_report.pdf")
# 构建索引(文本 + 图表描述统一索引)
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()
response = query_engine.query("报告中的架构图展示了哪些组件?")步骤 2:图文混合 RAG(Python + LlamaIndex)
from llama_index.core import SimpleDirectoryReader, VectorStoreIndex
from llama_index.multi_modal_llms.openai import OpenAIMultiModal
from llama_index.core.schema import ImageDocument, TextNode
# 加载文本和图像
text_docs = SimpleDirectoryReader("./docs/text/").load_data()
image_docs = SimpleDirectoryReader(
"./docs/images/",
file_extractor={".png": "image", ".jpg": "image"}
).load_data()
# 方案 A:用 GPT-4o 将图像转为文本描述后索引
mm_llm = OpenAIMultiModal(model="gpt-4o", max_new_tokens=500)
image_text_nodes = []
for img_doc in image_docs:
# 生成图像描述
description = mm_llm.complete(
prompt="详细描述这张图片的内容,包括所有文字、数据和关系。",
image_documents=[img_doc],
)
node = TextNode(
text=str(description),
metadata={
"source": img_doc.metadata.get("file_name"),
"type": "image_description",
"original_image_path": img_doc.metadata.get("file_path"),
}
)
image_text_nodes.append(node)
# 合并文本和图像描述,统一索引
all_nodes = [node for doc in text_docs for node in doc.to_nodes()] + image_text_nodes
index = VectorStoreIndex(nodes=all_nodes)步骤 3:使用 ColPali 进行视觉文档检索
# ColPali:直接对文档页面截图进行检索,无需 OCR
from colpali_engine.models import ColPali, ColPaliProcessor
import torch
from PIL import Image
# 加载模型
model = ColPali.from_pretrained(
"vidore/colpali-v1.3", torch_dtype=torch.bfloat16
).eval().cuda()
processor = ColPaliProcessor.from_pretrained("vidore/colpali-v1.3")
# 索引:将文档页面截图编码为向量
page_images = [Image.open(f"page_{i}.png") for i in range(10)]
with torch.no_grad():
batch = processor.process_images(page_images).to("cuda")
page_embeddings = model(**batch)
# 查询:将文本查询编码后与页面向量匹配
query = "2024年Q3的营收数据"
with torch.no_grad():
query_batch = processor.process_queries([query]).to("cuda")
query_embedding = model(**query_batch)
# 计算相似度
scores = processor.score_multi_vector(query_embedding, page_embeddings)
top_pages = scores[0].argsort(descending=True)[:3]
print(f"最相关的页面: {top_pages.tolist()}")提示词模板
你是一个多模态 RAG 系统设计师。请根据以下需求设计方案:
**数据源:**
- 文档类型:[PDF报告/PPT演示/技术手册/产品图册]
- 包含的模态:[纯文本/文本+表格/文本+图表/文本+图片+表格]
- 文档数量:[数量] 份,平均 [页数] 页
- 语言:[中文/英文/多语言]
**请输出:**
1. 推荐的文档解析方案(LlamaParse/Unstructured/自定义)
2. 多模态处理策略(统一嵌入/文本化/原生多模态)
3. 各模态的嵌入和索引方案
4. 检索和生成阶段的模型选择
5. 预估成本(按文档量计算解析和查询成本)5. Agentic RAG
核心原理
Agentic RAG 是 RAG 技术的最新演进方向,它将 AI Agent 的自主决策能力引入 RAG 流程。与传统 RAG 的固定流水线不同,Agentic RAG 中的 Agent 能够:
- 动态判断是否需要检索(有些问题 LLM 直接就能回答)
- 自主选择检索源(从多个知识库、API、数据库中选择)
- 迭代优化检索结果(如果第一次检索不满意,自动改写查询重试)
- 多步推理将复杂问题分解为多个检索-推理步骤
- 自我验证检查生成结果的事实一致性
Agentic RAG vs 传统 RAG:
| 维度 | 传统 RAG | Agentic RAG |
|---|---|---|
| 流程 | 固定流水线 | 动态决策 |
| 检索策略 | 单一策略 | 自适应多策略 |
| 错误处理 | 无自我修正 | 自动重试和改写 |
| 数据源 | 单一向量库 | 多源(向量库+API+SQL+Web) |
| 复杂查询 | 一次检索 | 多步分解和迭代 |
| 成本 | 低(单次调用) | 较高(多次 LLM 调用) |
工具推荐
| 工具 | 用途 | 价格 | 适用场景 |
|---|---|---|---|
| LangGraph | 构建有状态的 Agentic RAG | 免费(开源) | 复杂多步骤 RAG 工作流 |
| LlamaIndex Workflows | Agent + RAG 编排 | 免费(开源) | 文档密集型 Agentic RAG |
| CrewAI | 多 Agent 协作 RAG | 免费(开源) | 多角色协作检索和分析 |
| AutoGen | 微软多 Agent 框架 | 免费(开源) | 对话式 Agentic RAG |
| n8n | 低代码 Agentic RAG 工作流 | 免费(自托管);云版 €20/月起 | 快速搭建,非开发者友好 |
| Haystack | 模块化 RAG pipeline | 免费(开源) | 灵活的组件化 RAG |
操作步骤
步骤 1:使用 LangGraph 构建 Agentic RAG(Python)
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import Qdrant
from langchain_core.messages import HumanMessage
from typing import TypedDict, Literal
import json
# 定义状态
class AgentState(TypedDict):
query: str
retrieved_docs: list[str]
answer: str
needs_retrieval: bool
retry_count: int
search_queries: list[str]
llm = ChatOpenAI(model="gpt-4o-mini")
vectorstore = Qdrant.from_existing_collection(
embedding=OpenAIEmbeddings(model="text-embedding-3-small"),
collection_name="knowledge_base",
url="http://localhost:6333",
)
# 节点 1:路由决策——是否需要检索
def route_query(state: AgentState) -> AgentState:
response = llm.invoke([HumanMessage(content=f"""
分析以下查询,判断是否需要从知识库检索信息。
如果是常识性问题或简单计算,不需要检索。
如果涉及特定领域知识、最新信息或具体数据,需要检索。
查询: {state["query"]}
输出 JSON: {{"needs_retrieval": true/false, "reason": "..."}}
""")])
result = json.loads(response.content)
state["needs_retrieval"] = result["needs_retrieval"]
return state
# 节点 2:智能检索
def retrieve(state: AgentState) -> AgentState:
query = state["search_queries"][-1] if state["search_queries"] else state["query"]
docs = vectorstore.similarity_search(query, k=5)
state["retrieved_docs"] = [doc.page_content for doc in docs]
return state
# 节点 3:生成回答
def generate(state: AgentState) -> AgentState:
context = "\n\n".join(state.get("retrieved_docs", []))
response = llm.invoke([HumanMessage(content=f"""
基于以下上下文回答问题。如果上下文不足以回答,明确说明。
上下文: {context}
问题: {state["query"]}
""")])
state["answer"] = response.content
return state
# 节点 4:质量检查——是否需要重试
def check_quality(state: AgentState) -> AgentState:
response = llm.invoke([HumanMessage(content=f"""
评估以下回答的质量。检查:
1. 是否完整回答了问题
2. 是否有"信息不足"的表述
3. 是否需要更多检索
问题: {state["query"]}
回答: {state["answer"]}
输出 JSON: {{"quality": "good"/"needs_retry", "improved_query": "..."}}
""")])
result = json.loads(response.content)
if result["quality"] == "needs_retry" and state["retry_count"] < 2:
state["retry_count"] += 1
state["search_queries"].append(result.get("improved_query", state["query"]))
state["needs_retrieval"] = True
else:
state["needs_retrieval"] = False
return state
# 构建图
def should_retrieve(state: AgentState) -> Literal["retrieve", "generate"]:
return "retrieve" if state["needs_retrieval"] else "generate"
def should_retry(state: AgentState) -> Literal["retrieve", "end"]:
return "retrieve" if state["needs_retrieval"] else "end"
graph = StateGraph(AgentState)
graph.add_node("route", route_query)
graph.add_node("retrieve", retrieve)
graph.add_node("generate", generate)
graph.add_node("check", check_quality)
graph.set_entry_point("route")
graph.add_conditional_edges("route", should_retrieve)
graph.add_edge("retrieve", "generate")
graph.add_edge("generate", "check")
graph.add_conditional_edges("check", should_retry, {"retrieve": "retrieve", "end": END})
app = graph.compile()
# 运行
result = app.invoke({
"query": "我们的 RAG 系统在处理中文技术文档时的最佳分块策略是什么?",
"retrieved_docs": [],
"answer": "",
"needs_retrieval": False,
"retry_count": 0,
"search_queries": [],
})
print(result["answer"])步骤 2:使用 LlamaIndex 构建多源 Agentic RAG
from llama_index.core.agent import ReActAgent
from llama_index.core.tools import QueryEngineTool, ToolMetadata
from llama_index.core import VectorStoreIndex, SQLDatabase
from llama_index.core.query_engine import NLSQLTableQueryEngine
from llama_index.llms.openai import OpenAI
llm = OpenAI(model="gpt-4o-mini")
# 工具 1:向量知识库检索
vector_index = VectorStoreIndex.from_documents(documents)
vector_tool = QueryEngineTool(
query_engine=vector_index.as_query_engine(),
metadata=ToolMetadata(
name="knowledge_base",
description="搜索技术文档知识库,适合查找概念解释、最佳实践、架构设计等信息",
),
)
# 工具 2:SQL 数据库查询
sql_database = SQLDatabase.from_uri("sqlite:///analytics.db")
sql_engine = NLSQLTableQueryEngine(
sql_database=sql_database,
tables=["metrics", "costs", "usage_logs"],
)
sql_tool = QueryEngineTool(
query_engine=sql_engine,
metadata=ToolMetadata(
name="analytics_db",
description="查询分析数据库,适合获取具体的数据指标、成本统计、使用量等数值信息",
),
)
# 创建 Agent(自动选择工具)
agent = ReActAgent.from_tools(
tools=[vector_tool, sql_tool],
llm=llm,
verbose=True,
max_iterations=5,
)
# Agent 会自动判断使用哪个工具
response = agent.chat("上个月 RAG 系统的查询成本是多少?有什么优化建议?")
# Agent 会先查 SQL 获取成本数据,再查知识库获取优化建议提示词模板
你是一个 Agentic RAG 系统架构师。请设计一个智能检索 Agent:
**业务需求:**
- 应用场景:[客服问答/技术支持/研究助手/数据分析]
- 数据源:[向量库/SQL数据库/API/网页/混合]
- 查询复杂度:[简单事实/多步推理/对比分析/数据+知识混合]
- 延迟要求:[实时<2s/准实时<10s/离线]
**请输出:**
1. Agent 架构设计(路由→检索→生成→验证的流程图)
2. 路由策略(什么查询走什么路径)
3. 工具定义(每个数据源对应的工具描述)
4. 重试和自我修正策略
5. 成本控制机制(避免无限循环)
6. 推荐的框架和技术栈实战案例:企业知识库智能问答系统
场景描述
一家科技公司需要构建内部知识库问答系统,数据源包括:
- 5000+ 篇技术文档(Markdown/PDF)
- 200+ 张架构图和流程图
- 内部 Wiki(含表格和代码片段)
- Jira/Confluence 数据
案例分析
技术方案选择:
┌─────────────────────────────────────────────────────┐
│ 用户查询入口 │
└──────────────────────┬──────────────────────────────┘
▼
┌─────────────────────────────────────────────────────┐
│ 查询路由 Agent │
│ 判断:简单查询 → 直接检索 │
│ 复杂查询 → 查询分解 │
│ 模糊查询 → HyDE 转换 │
└──────────────────────┬──────────────────────────────┘
▼
┌─────────────────────────────────────────────────────┐
│ 混合检索层 │
│ BM25(精确关键词)+ 向量搜索(语义) │
│ → RRF 融合 → Top-50 │
└──────────────────────┬──────────────────────────────┘
▼
┌─────────────────────────────────────────────────────┐
│ 重排序层 │
│ Cohere Rerank v3.5 → Top-8 │
└──────────────────────┬──────────────────────────────┘
▼
┌─────────────────────────────────────────────────────┐
│ 生成 + 质量检查 │
│ GPT-4o 生成回答 → 事实一致性验证 │
│ 不满意 → 改写查询重试(最多 2 次) │
└─────────────────────────────────────────────────────┘关键决策点:
- 文档解析:使用 LlamaParse 处理 PDF 中的图表,将架构图转为文本描述后索引
- 混合搜索:Qdrant 原生支持稀疏+稠密混合搜索,alpha=0.7(偏向语义)
- 重排序:Cohere Rerank v3.5 处理技术文档效果优秀,支持代码和表格
- Agentic 层:LangGraph 实现路由和重试逻辑,最多 2 次重试控制成本
- 成本控制:简单查询跳过 HyDE 和重排序,复杂查询才启用全流程
效果对比:
| 指标 | Naive RAG | + 混合搜索 | + 重排序 | + Agentic |
|---|---|---|---|---|
| 检索精度(Precision@5) | 0.52 | 0.68 | 0.79 | 0.85 |
| 回答准确率 | 61% | 72% | 81% | 88% |
| 平均延迟 | 1.2s | 1.5s | 2.1s | 3.5s |
| 每次查询成本 | $0.003 | $0.004 | $0.006 | $0.012 |
避坑指南
❌ 常见错误
-
一开始就上 Agentic RAG
- 问题:Agentic RAG 增加了复杂度、延迟和成本,对简单场景是过度工程
- 正确做法:从 Naive RAG 开始,逐步添加混合搜索 → 重排序 → 查询转换 → Agentic,每步验证效果
-
HyDE 用于所有查询
- 问题:HyDE 增加一次 LLM 调用延迟(~500ms),对精确关键词查询反而降低效果
- 正确做法:仅对模糊、口语化查询启用 HyDE,精确查询直接走关键词搜索
-
重排序的 Top-K 设置过小
- 问题:初始检索只取 Top-10 再重排序,可能遗漏相关文档
- 正确做法:初始检索取 Top-50
100,重排序后取 Top-510,给重排序足够的候选池
-
多模态 RAG 忽略图像质量
- 问题:低分辨率图像、扫描件导致 OCR/视觉模型解析失败
- 正确做法:预处理阶段检查图像质量,低质量图像用专门的 OCR 工具处理
-
Agentic RAG 没有设置重试上限
- 问题:Agent 陷入”检索-不满意-重试”的无限循环,消耗大量 token
- 正确做法:设置最大重试次数(通常 2-3 次),超过后返回当前最佳结果并标注置信度
-
混合搜索的权重不调优
- 问题:使用默认的 alpha=0.5,没有根据数据特征调整
- 正确做法:在验证集上测试不同 alpha 值(0.3-0.8),技术文档通常偏向语义(0.6-0.8),法律/医疗文档偏向关键词(0.3-0.5)
✅ 最佳实践
- 渐进式优化:Naive RAG → 混合搜索 → 重排序 → 查询转换 → Agentic,每步用评估指标验证提升
- 建立评估基准:在添加任何高级技术前,先用 RAGAS 建立基线指标(详见 11f-RAG评估与优化)
- 成本感知设计:为不同复杂度的查询设计不同的处理路径,简单查询走快速通道
- 缓存策略:对高频查询缓存检索结果和生成回答,减少重复计算
- 监控和告警:监控每种技术的延迟、成本和效果指标,及时发现退化
- A/B 测试:新技术上线前进行 A/B 测试,用真实查询验证效果
相关资源与延伸阅读
- LangGraph RAG 教程 — LangGraph 官方仓库,包含 Agentic RAG 示例
- LlamaIndex 高级 RAG 指南 — LlamaIndex 官方文档,覆盖 HyDE、多模态等高级技术
- Qdrant 混合搜索教程 — Qdrant 官方混合搜索 + 重排序教程
- Cohere Rerank 最佳实践 — Cohere 重排序模型文档和使用指南
- ColPali 视觉文档检索 — ColPali 开源视觉文档检索模型
- RAGAS 评估框架 — RAG 系统自动化评估工具
- Reranker 排行榜 — 各重排序模型的质量、延迟、成本对比
- DSPy 框架 — 斯坦福开源的 LLM pipeline 自动优化框架
- Weaviate 混合搜索文档 — Weaviate 混合搜索配置指南
- HyDE 原始论文 — Hypothetical Document Embeddings 原始研究论文
参考来源
- The RAG Spectrum: Exploring 7 Distinct Architectures (2025-05)
- Agentic RAG: Everything AI Engineers Need to Know in 2026 (2025-06)
- Advanced RAG Techniques: Hybrid Search and Re-ranking (2025-12)
- Cohere Rerank 4: A Real Upgrade over 3.5 (2025-06)
- Better RAG with HyDE: Hypothetical Document Embeddings (2025-03)
- HyPE: Hypothetical Prompt Embeddings (2025-02)
- A Guide to Building Autonomous AI Systems — n8n Blog (2025-02)
- Multimodal Retrieval-Augmented Generation (2025-08)
- 9 Advanced RAG Techniques (2026-01)
- Cohere Rerank v3.5 on Azure AI Foundry (2025-03)
📖 返回 总览与导航 | 上一节:11d-RAG系统构建教程 | 下一节:11f-RAG评估与优化