RAG 检索增强生成入门:从理念到落地
大语言模型(LLM)能力很强,但有两个硬伤:知识截止——训练数据有截止日期,无法回答训练之后的事;幻觉问题——不知道的也敢编,一本正经地胡说八道。RAG(Retrieval-Augmented Generation,检索增强生成)就是解决这两个问题的主流方案。
本文从 RAG 的核心理念出发,覆盖架构设计、分块策略、模型选型、向量数据库对比、高级检索技巧、框架实现、评估监控到未来演进,力求一篇讲透。
一、什么是 RAG:解决 LLM 的两个硬伤
RAG 的核心思路极其简单:让 LLM 在回答问题之前,先去查资料。
类比人类:考试时闭卷答题 vs 开卷答题。RAG 就是给 LLM "开卷"——先从知识库中检索相关内容,再让 LLM 基于检索到的内容生成回答。
LLM 的两大痛点
| 痛点 | 表现 | RAG 如何解决 |
|---|---|---|
| 知识截止 | GPT-4 的训练数据截止到 2024 年,问 2025 年的事就答不了 | 从实时更新的外部知识库检索最新信息 |
| 幻觉(Hallucination) | 自信地编造不存在的事实、论文、链接 | 基于检索到的事实生成,答案有据可查 |
RAG vs 微调 vs 预训练
| 维度 | RAG | 微调(Fine-tuning) | 预训练(Pre-training) |
|---|---|---|---|
| 知识更新 | 实时(更新知识库即可) | 需要重新训练 | 需要重新训练 |
| 成本 | 低(检索 + 推理) | 中(训练成本) | 极高(大规模算力) |
| 可解释性 | 高(可追溯检索来源) | 低(知识隐含在权重中) | 低 |
| 适用场景 | 知识密集型问答 | 风格/格式适配 | 基础能力构建 |
二、RAG 经典架构:两条 Pipeline
RAG 系统由两条 Pipeline 组成:Indexing Pipeline(离线建索引)和 Retrieval Pipeline(在线检索生成)。
Indexing Pipeline(离线)
原始文档
→ 文档解析(PDF/HTML/Markdown → 纯文本)
→ 文档分块(Chunking)
→ 嵌入向量化(Embedding)
→ 存入向量数据库
这是数据准备的阶段,通常在用户查询之前完成。当知识库更新时,只需重新跑 Indexing Pipeline 即可。
Retrieval Pipeline(在线)
用户查询(Query)
→ Query Embedding
→ 向量相似度搜索(从向量库检索 Top-K)
→ 上下文组装(Query + 检索结果 → Prompt)
→ LLM 生成回答
这是用户实际交互的阶段,延迟是关键指标。
整体架构图
┌─────────────────────────────────────────────────────┐
│ Indexing Pipeline(离线) │
│ │
│ 文档 ──→ 解析 ──→ 分块 ──→ Embedding ──→ 向量库 │
│ │ │
└──────────────────────────────────────────────┼──────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ Retrieval Pipeline(在线) │
│ │
│ Query ──→ Embedding ──→ 相似度搜索 ──→ LLM ──→ 回答│
│ ↑ │
│ Top-K 文档块 │
└─────────────────────────────────────────────────────┘
三、文档分块策略
文档分块是 RAG 系统中最被低估但影响最大的环节。分块太大,检索不精准(噪声多);分块太小,上下文丢失(语义不完整)。
1. 固定长度分块(Fixed-Size Chunking)
最简单的策略:按字符数或 Token 数切割,可设置重叠(Overlap)以减少语义截断。
# LangChain 实现
from langchain.text_splitter import CharacterTextSplitter
splitter = CharacterTextSplitter(
chunk_size=500, # 每块 500 字符
chunk_overlap=50, # 相邻块重叠 50 字符
separator="\n" # 优先在换行处切割
)
chunks = splitter.split_text(document_text)
优点:实现简单、可预测。缺点:可能在句子中间截断,破坏语义完整性。
2. 递归分块(Recursive Character Chunking)
LangChain 的默认推荐策略。按优先级尝试多个分隔符(\n\n → \n → 。 → ),逐级降级。
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
separators=["\n\n", "\n", "。", "!", "?", " ", ""]
)
chunks = splitter.split_text(document_text)
优点:尽量保持段落/句子完整性。缺点:分块大小不够均匀。
3. 语义分块(Semantic Chunking)
基于嵌入向量的语义相似度来决定分界点——当相邻句子的语义相似度低于阈值时,就在此处切割。
from langchain_experimental.text_splitter import SemanticChunker
from langchain_openai import OpenAIEmbeddings
splitter = SemanticChunker(
OpenAIEmbeddings(),
breakpoint_threshold_type="percentile", # 按百分位阈值
breakpoint_threshold_amount=75 # 75th 百分位
)
chunks = splitter.split_text(document_text)
优点:语义边界最自然。缺点:计算成本高(需要先对每个句子做嵌入),分块大小不可控。
三种分块策略对比
| 维度 | 固定长度 | 递归分块 | 语义分块 |
|---|---|---|---|
| 实现复杂度 | ⭐ 低 | ⭐⭐ 中 | ⭐⭐⭐ 高 |
| 分块大小均匀 | ✅ 均匀 | ⚠️ 较均匀 | ❌ 不均匀 |
| 语义完整性 | ❌ 可能截断 | ⚠️ 较好 | ✅ 最好 |
| 计算成本 | 低 | 低 | 高(需要嵌入) |
| 推荐场景 | 快速原型 / 结构化文档 | ✅ 通用首选 | 高精度要求 / 非结构化文档 |
四、嵌入模型选型
嵌入模型(Embedding Model)将文本转换为固定维度的向量,是检索质量的基石。选错模型,后面所有优化都是徒劳。
主流嵌入模型对比
| 模型 | 维度 | MTEB 均值 | 中文支持 | 开源 | 特点 |
|---|---|---|---|---|---|
| BGE-large-zh-v1.5 | 1024 | ~64 | ✅ 优秀 | ✅ | 中文场景首选,智源出品 |
| BGE-M3 | 1024 | ~67 | ✅ 多语言 | ✅ | 多语言多粒度多功能,一站式 |
| M3E-large | 1024 | ~62 | ✅ 优秀 | ✅ | 中文领域微调效果好 |
| text2vec-large-chinese | 1024 | ~58 | ✅ | ✅ | 轻量级,适合快速验证 |
| OpenAI text-embedding-3-large | 3072 | ~68 | ⚠️ 可用 | ❌ | 效果最好,但需 API 调用 |
| OpenAI text-embedding-3-small | 1536 | ~65 | ⚠️ 可用 | ❌ | 性价比高,英文为主 |
选型决策
主要语言是中文?
├── 是 → 需要私有化部署?
│ ├── 是 → BGE-large-zh-v1.5(中文首选)或 BGE-M3(多语言)
│ └── 否 → OpenAI text-embedding-3-large(效果最好)
└── 否 → 需要私有化部署?
├── 是 → BGE-M3 或 sentence-transformers 系列
└── 否 → OpenAI text-embedding-3-small(性价比)或 large(效果)
五、向量数据库对比
向量数据库存储嵌入向量并支持高效相似度搜索,是 RAG 的基础设施。
主流向量数据库对比
| 数据库 | 类型 | 开源 | 规模 | 混合检索 | 托管服务 | 适合场景 |
|---|---|---|---|---|---|---|
| Milvus | 专用向量库 | ✅ | 十亿级 | ✅(2.4+) | Zilliz Cloud | 大规模生产环境 |
| Pinecone | 全托管服务 | ❌ | 十亿级 | ✅ | 本身就是 | 不想运维、快速上线 |
| Qdrant | 专用向量库 | ✅ | 亿级 | ✅ | Qdrant Cloud | Rust 高性能、过滤友好 |
| Chroma | 轻量级向量库 | ✅ | 百万级 | ⚠️ 有限 | ❌ | 原型开发、小规模应用 |
| FAISS | 向量索引库 | ✅ | 十亿级 | ❌ | ❌ | 纯相似度搜索、不需 CRUD |
选型建议
数据规模 & 使用场景:
├── 学习 / 原型验证 → Chroma(最简单,pip install 即用)
├── 中小规模生产(<1000 万向量)→ Qdrant(性能好、过滤强、易部署)
├── 大规模生产(>1 亿向量)→ Milvus(分布式、水平扩展)
├── 不想运维 → Pinecone(全托管,按量付费)
└── 纯批处理 / 不需在线 CRUD → FAISS(Meta 出品,极致性能)
六、检索增强策略
有了基础的向量检索,下一步是提升检索质量。以下是四种从简单到高级的检索策略。
1. 简单检索(Naive Retrieval)
最基础的方案:Query → Embedding → Top-K 相似度搜索。简单但粗糙,问题在于用户提问的方式和文档表述的方式可能差异很大。
# LangChain 简单检索
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
vectorstore = Chroma.from_documents(docs, OpenAIEmbeddings())
retriever = vectorstore.as_retriever(search_kwargs={"k": 4})
results = retriever.invoke("什么是 RAG?")
2. HyDE(Hypothetical Document Embedding)
核心思想:先让 LLM 生成一个"假设性回答",再用这个回答去检索。假设性回答的表述方式更接近文档,从而弥合 Query 与文档之间的语义鸿沟。
# HyDE 流程
# 步骤1:LLM 生成假设性回答
query = "如何优化 RAG 的检索精度?"
hypothetical_answer = llm.invoke(
f"请回答以下问题,即使你不确定也给出详细回答:\n{query}"
)
# 步骤2:用假设性回答(而非原始 Query)去检索
results = vectorstore.similarity_search(hypothetical_answer, k=4)
# LangChain 内置实现
from langchain.retrievers import HypotheticalDocumentEmbedder
hyde_retriever = HypotheticalDocumentEmbedder.from_llm(
llm, vectorstore, "web_search" # prompt_key
)
results = hyde_retriever.invoke(query)
3. RAG-Fusion
RAG-Fusion 的策略是:用 LLM 将原始查询改写为多个不同角度的查询,分别检索,再对结果做互惠排序融合(Reciprocal Rank Fusion, RRF)。
# RAG-Fusion 流程
query = "RAG 的最佳实践"
# 步骤1:生成多个查询变体
query_variants = llm.invoke(f"""
生成以下问题的 4 个不同表述方式:
{query}
""").split("\n") # ["RAG 实践指南", "RAG 优化技巧", ...]
# 步骤2:分别检索
all_results = []
for q in [query] + query_variants:
all_results.append(vectorstore.similarity_search(q, k=4))
# 步骤3:互惠排序融合(RRF)
def reciprocal_rank_fusion(lists_of_docs, k=60):
scores = {}
for doc_list in lists_of_docs:
for rank, doc in enumerate(doc_list):
key = doc.page_content
scores[key] = scores.get(key, 0) + 1 / (rank + k)
# 按融合分数排序
return sorted(scores.items(), key=lambda x: x[1], reverse=True)
fused_results = reciprocal_rank_fusion(all_results)
RAG-Fusion 的优势在于多角度覆盖——不同的查询表述可能命中不同文档,融合后召回率更高。
4. Parent Document Retriever
核心问题:小分块检索精准但上下文不足,大分块上下文完整但检索不精准。Parent Document Retriever 用小分块检索,但返回对应的大分块(父文档)。
from langchain.retrievers import ParentDocumentRetriever
from langchain.storage import InMemoryStore
# 小分块用于检索(精准)
child_splitter = RecursiveCharacterTextSplitter(chunk_size=200)
# 大分块用于返回给 LLM(上下文完整)
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=1000)
# 存储父子映射关系
docstore = InMemoryStore()
retriever = ParentDocumentRetriever(
vectorstore=vectorstore, # 存小分块的向量
docstore=docstore, # 存大分块的原文
child_splitter=child_splitter,
parent_splitter=parent_splitter,
)
retriever.add_documents(docs)
results = retriever.invoke(query) # 返回大分块
四种检索策略对比
| 策略 | 额外 LLM 调用 | 延迟 | 召回率 | 精度 | 适用场景 |
|---|---|---|---|---|---|
| 简单检索 | 0 | 低 | 低 | 中 | 基线 / 概念验证 |
| HyDE | 1 | 中 | 中高 | 中高 | 模糊/简短查询 |
| RAG-Fusion | 1 | 高 | 高 | 中高 | 需要广覆盖 |
| Parent Document | 0 | 低 | 中 | 高 | 需要上下文完整性 |
七、高级优化:Reranker、混合检索与查询改写
1. Reranker(重排序)
向量检索基于嵌入相似度,是一种"粗排"。Reranker 是"精排"——用交叉编码器(Cross-Encoder)对 Query-Document 对做精细的相关性打分。
# Cohere Reranker(推荐,效果最好)
from langchain.retrievers import ContextualCompressionRetriever
from langchain_cohere import CohereRerank
compressor = CohereRerank(top_n=4)
compression_retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=vectorstore.as_retriever(search_kwargs={"k": 20})
)
# 先检索 20 个,Rerank 后返回 Top-4
results = compression_retriever.invoke(query)
# 本地 Reranker(无需 API Key)
from langchain.retrievers.document_compressors import CrossEncoderReranker
from langchain_community.cross_encoders import HuggingFaceCrossEncoder
model = HuggingFaceCrossEncoder(model_name="BAAI/bge-reranker-v2-m3")
compressor = CrossEncoderReranker(model=model, top_n=4)
2. 混合检索(Hybrid Search)
向量检索擅长语义匹配,但可能漏掉精确关键词(如产品型号、人名、专有名词)。混合检索 = 向量检索 + 关键词检索(BM25),取长补短。
# LangChain EnsembleRetriever
from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever
# 稀疏检索:BM25(关键词匹配)
bm25_retriever = BM25Retriever.from_documents(docs, k=5)
# 稠密检索:向量检索(语义匹配)
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
# 混合检索:各占 50% 权重
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, vector_retriever],
weights=[0.5, 0.5]
)
results = ensemble_retriever.invoke(query)
Qdrant 和 Milvus 原生支持混合检索,不需要额外部署 BM25。
3. Query Rewriting(查询改写)
用户提问往往不够清晰,Query Rewriting 用 LLM 将原始查询改写为更适合检索的形式。
# 多查询改写(Multi-Query)
from langchain.retrievers.multi_query import MultiQueryRetriever
retriever = MultiQueryRetriever.from_llm(
retriever=vectorstore.as_retriever(search_kwargs={"k": 4}),
llm=llm
)
# 自动生成多个查询变体,分别检索,合并去重
results = retriever.invoke(query)
# Step-back Prompting(后退提问)
# 让 LLM 生成一个更宽泛的"后退问题"
step_back_prompt = """
你是一个专家。针对以下具体问题,生成一个更宽泛、更一般化的问题,
用于检索背景知识。
原始问题:{question}
后退问题:
"""
step_back_query = llm.invoke(step_back_prompt.format(question=query))
# 同时用原始问题和后退问题检索
original_results = vectorstore.similarity_search(query, k=3)
background_results = vectorstore.similarity_search(step_back_query, k=3)
优化策略组合
推荐优化路径(按性价比排序):
1. 基线:简单向量检索 → 建立基准
2. +Reranker → 精度显著提升,改动最小
3. +混合检索(向量 + BM25) → 召回率提升,尤其对专有名词
4. +Query Rewriting / Multi-Query → 模糊查询场景改善
5. +HyDE / RAG-Fusion → 进一步提升召回
6. +Parent Document Retriever → 解决上下文截断问题
八、LangChain / LlamaIndex 实现示例
LangChain 完整 RAG 示例
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import ChatPromptTemplate
# 1. 加载文档
loader = PyPDFLoader("knowledge_base.pdf")
docs = loader.load()
# 2. 分块
splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50
)
chunks = splitter.split_documents(docs)
# 3. 创建向量库
vectorstore = Chroma.from_documents(
chunks,
OpenAIEmbeddings(),
persist_directory="./chroma_db"
)
# 4. 创建检索器(带 Reranker)
retriever = vectorstore.as_retriever(search_kwargs={"k": 10})
# 5. 创建 LLM 和 Prompt
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
system_prompt = """你是一个知识助手。使用以下检索到的上下文来回答用户的问题。
如果你不知道答案,就说不知道,不要编造。
上下文中的信息必须在答案中引用来源。
上下文:
{context}"""
prompt = ChatPromptTemplate.from_messages([
("system", system_prompt),
("human", "{input}"),
])
# 6. 创建 RAG Chain
question_answer_chain = create_stuff_documents_chain(llm, prompt)
rag_chain = create_retrieval_chain(retriever, question_answer_chain)
# 7. 查询
response = rag_chain.invoke({"input": "什么是 RAG?"})
print(response["answer"])
LlamaIndex 完整 RAG 示例
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
from llama_index.core.node_parser import SentenceSplitter
from llama_index.llms.openai import OpenAI
from llama_index.embeddings.openai import OpenAIEmbedding
# 1. 配置全局设置
Settings.llm = OpenAI(model="gpt-4o-mini", temperature=0)
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")
# 2. 加载文档
documents = SimpleDirectoryReader("./data").load_data()
# 3. 分块
splitter = SentenceSplitter(chunk_size=500, chunk_overlap=50)
Settings.transformations = [splitter]
# 4. 创建索引
index = VectorStoreIndex.from_documents(documents)
# 5. 创建查询引擎
query_engine = index.as_query_engine(
similarity_top_k=5,
response_mode="tree_summarize" # 或 "compact", "refine"
)
# 6. 查询
response = query_engine.query("什么是 RAG?")
print(response)
# 7. 查看引用来源
for source_node in response.source_nodes:
print(f"来源: {source_node.node.metadata}")
print(f"分数: {source_node.score:.4f}")
print(f"内容: {source_node.node.text[:100]}...")
LangChain vs LlamaIndex 对比
| 维度 | LangChain | LlamaIndex |
|---|---|---|
| 定位 | 通用 LLM 应用框架 | 专注 RAG / 数据索引 |
| 学习曲线 | 较陡(概念多) | 较平(RAG 开箱即用) |
| 灵活性 | 高(Chain、Agent、Tool 自由组合) | 中(聚焦索引和查询) |
| RAG 开箱体验 | 需要手动组装 | 一行代码查询 |
| 推荐场景 | 复杂 Agent / 多工具调用 | 纯 RAG / 知识库问答 |
九、评估与监控:RAGAS 框架
没有评估就无法优化。RAGAS(Retrieval Augmented Generation Assessment)是 RAG 系统的事实标准评估框架。
RAGAS 核心指标
检索质量指标
| 指标 | 含义 | 计算方式 | 越高越好? |
|---|---|---|---|
| Context Precision | 检索结果中相关文档的排名是否靠前 | Top-K 中相关文档的精确率加权 | ✅ |
| Context Recall | 回答所需的信息是否都被检索到了 | Ground Truth 中的声明在 Context 中出现的比例 | ✅ |
生成质量指标
| 指标 | 含义 | 计算方式 | 越高越好? |
|---|---|---|---|
| Faithfulness | 回答是否忠于检索到的上下文(不编造) | 回答中的声明在 Context 中有支撑的比例 | ✅ |
| Answer Relevancy | 回答是否切题 | 从回答反推问题的相似度 | ✅ |
| Answer Similarity | 回答与 Ground Truth 的语义相似度 | 嵌入向量的余弦相似度 | ✅ |
RAGAS 使用示例
from ragas import evaluate
from ragas.metrics import (
context_precision,
context_recall,
faithfulness,
answer_relevancy,
)
from datasets import Dataset
# 准备评估数据集
data = {
"question": ["什么是 RAG?", "RAG 有哪些优化策略?"],
"answer": [
"RAG 是检索增强生成...",
"RAG 优化策略包括 HyDE、RAG-Fusion..."
],
"contexts": [
["RAG 是 Retrieval-Augmented Generation 的缩写..."],
["HyDE 通过假设性文档嵌入...", "RAG-Fusion 使用多查询..."]
],
"ground_truth": [
"RAG 是通过检索外部知识来增强 LLM 生成的技术",
"RAG 优化包括 HyDE、RAG-Fusion、Reranker、混合检索等"
]
}
dataset = Dataset.from_dict(data)
# 评估
results = evaluate(
dataset,
metrics=[
context_precision,
context_recall,
faithfulness,
answer_relevancy,
]
)
print(results)
# {'context_precision': 0.85, 'context_recall': 0.90,
# 'faithfulness': 0.88, 'answer_relevancy': 0.92}
监控指标(生产环境)
| 指标类别 | 指标 | 目标值 |
|---|---|---|
| 延迟 | P95 端到端延迟 | < 3s |
| 检索质量 | Top-5 检索相关率 | > 80% |
| 生成质量 | Faithfulness | > 90% |
| 用户满意度 | 👍/👎 比例 | > 85% 👍 |
| 成本 | 每次查询 Token 消耗 | 监控趋势 |
十、Agentic RAG 与未来演进
从 Naive RAG 到 Agentic RAG
经典 RAG 是单轮检索-生成的固定管线。Agentic RAG 将 LLM 作为 Agent,让系统自主决定"何时检索、检索什么、是否需要再检索"。
# Agentic RAG 简化流程
while not confident_enough:
1. Agent 判断是否需要检索
2. 如果需要 → 构造查询 → 检索 → 阅读
3. 判断信息是否充分
4. 如果不充分 → 改写查询 → 再检索
5. 如果充分 → 生成最终回答
Agentic RAG 的关键特征
| 特征 | 经典 RAG | Agentic RAG |
|---|---|---|
| 检索决策 | 每次查询都检索 | Agent 判断是否需要检索 |
| 查询构造 | 直接用用户原始查询 | Agent 自主构造查询 |
| 迭代检索 | 单轮检索 | 可多轮检索,逐步聚焦 |
| 工具使用 | 仅检索 | 检索 + 计算 + API 调用等 |
| 自我反思 | 无 | 验证答案是否可靠 |
Agentic RAG 实现示例(LangChain)
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain_core.tools import tool
@tool
def search_knowledge_base(query: str) -> str:
"""搜索内部知识库,返回相关文档内容"""
docs = vectorstore.similarity_search(query, k=3)
return "\n\n".join([d.page_content for d in docs])
@tool
def search_web(query: str) -> str:
"""搜索互联网,获取最新信息"""
# 调用搜索 API
return web_search_api(query)
tools = [search_knowledge_base, search_web]
agent = create_tool_calling_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
# Agent 自主决定用哪个工具、检索几次
result = agent_executor.invoke({
"input": "比较 Milvus 和 Qdrant 的最新性能基准测试结果"
})
未来演进方向
- GraphRAG:基于知识图谱的 RAG,用实体关系图替代纯向量检索,擅长处理跨文档的复杂推理
- 多模态 RAG:支持图片、表格、视频的检索和生成,不只限于文本
- 自适应分块:根据查询类型动态调整分块策略和大小
- 个性化 RAG:结合用户画像和历史对话,提供个性化的检索和生成
- 端侧 RAG:在设备本地运行轻量级 RAG,降低延迟和成本
十一、速查表
| 环节 | 推荐方案 | 关键参数 |
|---|---|---|
| 文档分块 | RecursiveCharacterTextSplitter | chunk_size=500, overlap=50 |
| 嵌入模型(中文) | BGE-large-zh-v1.5 | dim=1024 |
| 嵌入模型(多语言) | BGE-M3 | dim=1024, 稠密+稀疏 |
| 嵌入模型(API) | OpenAI text-embedding-3-large | dim=3072 |
| 向量库(开发) | Chroma | pip install 即用 |
| 向量库(生产) | Milvus / Qdrant | 分布式 / 高性能 |
| 第一优化 | + Reranker | Cohere / BGE-Reranker |
| 第二优化 | + 混合检索 | 向量 + BM25 |
| 模糊查询优化 | HyDE / Multi-Query | LLM 改写查询 |
| 上下文截断 | Parent Document Retriever | 小分块检索,大分块返回 |
| 评估框架 | RAGAS | Faithfulness + Context Recall |
| RAG 框架(纯 RAG) | LlamaIndex | 开箱即用 |
| RAG 框架(Agent) | LangChain | 灵活组合 |